usb_dev_handle *usb_open(struct usb_device *dev) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbOpen); pkt_adduint(pkt, dev->bus->location); pkt_adduint(pkt, dev->devnum); pkt_send(pkt, fd); // Get response int res = -1, devfd = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbOpen) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); devfd = iter_getint(&it); } // Evaluate usb_dev_handle* udev = NULL; if(res >= 0) { udev = malloc(sizeof(usb_dev_handle)); udev->fd = devfd; udev->device = dev; udev->bus = dev->bus; udev->config = udev->interface = udev->altsetting = -1; } pkt_release(); debug_msg("returned %d (fd %d)", res, devfd); return udev; }
/* libusb(5): * Interrupt transfers. */ int usb_interrupt_write(usb_dev_handle *dev, int ep, usb_buf_t bytes, int size, int timeout) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbInterruptWrite); pkt_addint(pkt, dev->fd); pkt_addint(pkt, ep); pkt_addstr(pkt, size, bytes); pkt_addint(pkt, timeout); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbInterruptWrite) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_reset(usb_dev_handle *dev) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbReset); pkt_addint(pkt, dev->fd); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbReset) { Iterator it; pkt_begin(pkt, &it); // Read result res = iter_getint(&it); } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name, unsigned int namelen) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbGetKernelDriver); pkt_addint(pkt, dev->fd); pkt_addint(pkt, interface); pkt_adduint(pkt, namelen); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbGetKernelDriver) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); // Error if(res) { error_msg("%s: could not get bound driver", __func__); } // Save string strncpy(name, iter_getstr(&it), namelen - 1); name[namelen - 1] = '\0'; } pkt_release(); debug_msg("returned %d (%s)", res, name); return res; }
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbInterruptRead); pkt_addint(pkt, dev->fd); pkt_addint(pkt, ep); pkt_addint(pkt, size); pkt_addint(pkt, timeout); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbInterruptRead) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); if(res > 0) { int minlen = (res > size) ? size : res; memcpy(bytes, it.val, minlen); } } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
static BOOL modem_command (const char *cmd, const char *resp, int timeout) { DWORD timer; int len = cmd ? strlen (cmd) : strlen (resp); if (cmd) rc = pkt_send (cmd, len); /**<\todo Bypass PKTDRVR ? */ if (rc < len || !_eth_is_init) return (FALSE); timer = set_timeout (1000 * timeout); while (!chk_timeout(timer)) { char *pkt = (char*) _eth_arrived (NULL NULL); if (!pkt) continue; outsn (pkt, len); /* print the modem echo */ _eth_free (pkt, type); return (strncmp(pkt,resp,strlen(resp)) == 0); /* got modem response */ } return (FALSE); }
int usb_set_altinterface(usb_dev_handle *dev, int alternate) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbSetAltInterface); pkt_addint(pkt, dev->fd); pkt_addint(pkt, alternate); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbSetAltInterface) { Iterator it; pkt_begin(pkt, &it); // Read result res = iter_getint(&it); // Read callback configuration alternate = iter_getint(&it); } // Save configuration dev->altsetting = alternate; // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_close(usb_dev_handle *dev) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbClose); pkt_addint(pkt, dev->fd); pkt_send(pkt, fd); // Free device free(dev); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbClose) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); } pkt_release(); debug_msg("returned %d", res); return res; }
static int tok_mac_xmit (const void *buf, WORD len) { SIO_TRACE (("tok_mac_xmit, len %d", len)); if (len > TOK_MAX) /* Token-Ring has no min. length */ len = TOK_MAX; return pkt_send (buf, len); }
static int fddi_mac_xmit (const void *buf, WORD len) { SIO_TRACE (("fddi_mac_xmit, len %d", len)); if (len < FDDI_MIN) len = FDDI_MIN; else if (len > FDDI_MAX) len = FDDI_MAX; return pkt_send (buf, len); }
static int arcnet_mac_xmit (const void *buf, WORD len) { SIO_TRACE (("arcnet_mac_xmit, len %d", len)); if (len < ARCNET_MIN) len = ARCNET_MIN; else if (len > ARCNET_MAX) len = ARCNET_MAX; return pkt_send (buf, len); }
/** * Functions called via function pointer `mac_transmit' to * actually send the data. */ static int eth_mac_xmit (const void *buf, WORD len) { SIO_TRACE (("eth_mac_xmit, len %d", len)); if (len < ETH_MIN) len = ETH_MIN; /* zero padding already done in eth_mac_format() */ else if (len > ETH_MAX) len = ETH_MAX; return pkt_send (buf, len); }
/** Initialize USB subsystem. */ void usb_init(void) { // Initialize packet & remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Create buffer pkt_init(pkt, UsbInit); pkt_send(pkt, fd); pkt_release(); // Initialize locally debug_msg("called"); }
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Prepare packet pkt_init(pkt, UsbControlMsg); pkt_addint(pkt, dev->fd); pkt_addint(pkt, requesttype); pkt_addint(pkt, request); pkt_addint(pkt, value); pkt_addint(pkt, index); pkt_addstr(pkt, size, bytes); pkt_addint(pkt, timeout); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbControlMsg) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); if(res > 0) { int minlen = (res > size) ? size : res; memcpy(bytes, it.val, minlen); } } // Return response pkt_release(); debug_msg("returned %d", res); return res; }
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Send packet pkt_init(pkt, UsbDetachKernelDriver); pkt_addint(pkt, dev->fd); pkt_addint(pkt, interface); pkt_send(pkt, fd); // Get response int res = -1; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbDetachKernelDriver) { Iterator it; pkt_begin(pkt, &it); res = iter_getint(&it); } pkt_release(); debug_msg("returned %d", res); return res; }
/** Find busses on remote host. \warning Does not transfer busses to local virtual bus list. */ int usb_find_busses(void) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Initialize pkt pkt_init(pkt, UsbFindBusses); pkt_send(pkt, fd); // Get number of changes int res = 0; Iterator it; if(pkt_recv(fd, pkt) > 0 && pkt_op(pkt) == UsbFindBusses) { if(pkt_begin(pkt, &it) != NULL) { res = iter_getint(&it); } } // Return remote result pkt_release(); debug_msg("returned %d", res); return res; }
/*---------------------------------------------------------------------------*/ void icmp_pkt_rx (netif_t *netif, net_buf_t *net_buf) { icmp_hdr_t *icmp_pkt_in, *icmp_pkt_out ; ipv4_hdr_t *ipv4_hdr_in, *ipv4_hdr_out ; eth_hdr_t *eth_hdr_in ; pkt_t *pkt ; eth_hdr_in = (eth_hdr_t *) ((usys) net_buf->data) ; ipv4_hdr_in = (ipv4_hdr_t *) (((usys) net_buf->data) + ETH_HDR_SIZE) ; icmp_pkt_in = (icmp_hdr_t *) (((usys) net_buf->data) + ETH_HDR_SIZE + IPV4_HDR_SIZE) ; switch (icmp_pkt_in->type) { case MSG_TYPE_ECHO_REQUEST : /* Alloc the frame */ if ((pkt = pkt_alloc (netif)) == NULL) { printf ("ERR: pkt_alloc() failed in handle_arp_pkt() !!\n") ; return ; } /* Fill out the icmp header and data */ icmp_pkt_out = (icmp_hdr_t *) (((usys) pkt) + ETH_HDR_SIZE + IPV4_HDR_SIZE) ; icmp_pkt_out->type = MSG_TYPE_ECHO_REPLY ; icmp_pkt_out->code = 0 ; icmp_pkt_out->id = icmp_pkt_in->id ; icmp_pkt_out->seq = icmp_pkt_in->seq ; memcpy (++icmp_pkt_out, ++icmp_pkt_in, ntohs(ipv4_hdr_in->len) - IPV4_HDR_SIZE - ICMP_HDR_SIZE) ; icmp_pkt_out -- ; icmp_pkt_out->csum = ~crc16_calc ((u8 *) icmp_pkt_out, ntohs(ipv4_hdr_in->len) - IPV4_HDR_SIZE) ; /* Initialize the ip header */ ipv4_hdr_out = (ipv4_hdr_t *) (((usys) pkt) + ETH_HDR_SIZE) ; ipv4_hdr_init (netif, ipv4_hdr_out, ntohs(ipv4_hdr_in->len), IPV4_PROTOCOL_ICMP, ntohl(ipv4_hdr_in->src)) ; /* Initialize the eth header */ eth_hdr_init (netif, pkt, eth_hdr_in->src_mac, ETH_TYPE_IPV4) ; pkt_send (netif, pkt, ntohs(ipv4_hdr_in->len) + ETH_HDR_SIZE) ; pkt_free (netif, pkt) ; break ; default : break ; } } /* End of function icmp_pkt_rx () */
static int null_mac_xmit (const void *buf, WORD len) { SIO_TRACE (("null_mac_xmit, len %d", len)); return pkt_send (buf, len); }
int nmrp_do(struct nmrpd_args *args) { struct nmrp_pkt tx, rx; uint8_t *src, dest[6]; uint16_t len, region; char *filename; time_t beg; int i, status, ulreqs, expect, upload_ok, autoip; struct ethsock *sock; uint32_t intf_addr; void (*sigh_orig)(int); struct { struct in_addr addr; struct in_addr mask; } PACKED ipconf; if (args->op != NMRP_UPLOAD_FW) { fprintf(stderr, "Operation not implemented.\n"); return 1; } if (!mac_parse(args->mac, dest)) { fprintf(stderr, "Invalid MAC address '%s'.\n", args->mac); return 1; } if ((ipconf.mask.s_addr = inet_addr(args->ipmask)) == INADDR_NONE) { fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask); return 1; } if (!args->ipaddr) { autoip = true; /* The MAC of the device that was used to test this utility starts * with a4:2b:8c, hence 164 (0xa4) and 183 (0x2b + 0x8c) */ args->ipaddr = "10.164.183.252"; if (!args->ipaddr_intf) { args->ipaddr_intf = "10.164.183.253"; } } else if (args->ipaddr_intf) { autoip = true; } else { autoip = false; } if ((ipconf.addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) { fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr); return 1; } if (args->ipaddr_intf && (intf_addr = inet_addr(args->ipaddr_intf)) == INADDR_NONE) { fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr_intf); return 1; } if (args->file_local && strcmp(args->file_local, "-") && access(args->file_local, R_OK) == -1) { fprintf(stderr, "Error accessing file '%s'.\n", args->file_local); return 1; } if (args->file_remote) { if (!tftp_is_valid_filename(args->file_remote)) { fprintf(stderr, "Invalid remote filename '%s'.\n", args->file_remote); return 1; } } if (args->region) { region = htons(to_region_code(args->region)); if (!region) { fprintf(stderr, "Invalid region code '%s'.\n", args->region); return 1; } } else { region = 0; } status = 1; sock = ethsock_create(args->intf, ETH_P_NMRP); if (!sock) { return 1; } gsock = sock; garp = 0; sigh_orig = signal(SIGINT, sigh); if (!autoip) { status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); if (status <= 0) { if (!status) { fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n", args->ipaddr, args->ipmask, args->intf); } goto out; } } else { if (verbosity) { printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf); } if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &gundo) != 0) { goto out; } } if (ethsock_set_timeout(sock, args->rx_timeout)) { goto out; } src = ethsock_get_hwaddr(sock); if (!src) { goto out; } memcpy(tx.eh.ether_shost, src, 6); memcpy(tx.eh.ether_dhost, dest, 6); tx.eh.ether_type = htons(ETH_P_NMRP); msg_init(&tx.msg, NMRP_C_ADVERTISE); msg_opt_add(&tx.msg, NMRP_O_MAGIC_NO, "NTGR", 4); msg_hton(&tx.msg); i = 0; upload_ok = 0; beg = time(NULL); while (1) { printf("\rAdvertising NMRP server on %s ... %c", args->intf, spinner[i]); fflush(stdout); i = (i + 1) & 3; if (pkt_send(sock, &tx) < 0) { perror("sendto"); goto out; } status = pkt_recv(sock, &rx); if (status == 0 && memcmp(rx.eh.ether_dhost, src, 6) == 0) { break; } else if (status == 1) { goto out; } else { if ((time(NULL) - beg) >= 60) { printf("\nNo response after 60 seconds. Bailing out.\n"); goto out; } } } printf("\n"); expect = NMRP_C_CONF_REQ; ulreqs = 0; do { if (expect != NMRP_C_NONE && rx.msg.code != expect) { fprintf(stderr, "Received %s while waiting for %s!\n", msg_code_str(rx.msg.code), msg_code_str(expect)); } msg_init(&tx.msg, NMRP_C_NONE); status = 1; switch (rx.msg.code) { case NMRP_C_ADVERTISE: printf("Received NMRP advertisement from %s.\n", mac_to_str(rx.eh.ether_shost)); status = 1; goto out; case NMRP_C_CONF_REQ: tx.msg.code = NMRP_C_CONF_ACK; msg_opt_add(&tx.msg, NMRP_O_DEV_IP, &ipconf, 8); msg_opt_add(&tx.msg, NMRP_O_FW_UP, NULL, 0); #ifdef NMRPFLASH_SET_REGION if (region) { msg_opt_add(&tx.msg, NMRP_O_DEV_REGION, ®ion, 2); } #endif expect = NMRP_C_TFTP_UL_REQ; printf("Received configuration request from %s.\n", mac_to_str(rx.eh.ether_shost)); memcpy(tx.eh.ether_dhost, rx.eh.ether_shost, 6); printf("Sending configuration: ip %s, mask %s.\n", args->ipaddr, args->ipmask); memcpy(arpmac, rx.eh.ether_shost, 6); memcpy(&arpip, &ipconf.addr, sizeof(ipconf.addr)); if (ethsock_arp_add(sock, arpmac, &arpip) != 0) { goto out; } garp = 1; break; case NMRP_C_TFTP_UL_REQ: if (!upload_ok) { if (++ulreqs > 5) { printf("Bailing out after %d upload requests.\n", ulreqs); tx.msg.code = NMRP_C_CLOSE_REQ; break; } } else { if (verbosity) { printf("Ignoring extra upload request.\n"); } ethsock_set_timeout(sock, args->ul_timeout); tx.msg.code = NMRP_C_KEEP_ALIVE_REQ; break; } len = 0; filename = msg_opt_data(&rx.msg, NMRP_O_FILE_NAME, &len); if (filename) { if (!args->file_remote) { args->file_remote = filename; } printf("Received upload request: filename '%.*s'.\n", len, filename); } else if (!args->file_remote) { args->file_remote = args->file_local; printf("Received upload request with empty filename.\n"); } status = 0; if (args->tftpcmd) { printf("Executing '%s' ... \n", args->tftpcmd); setenv("IP", inet_ntoa(ipconf.addr), 1); setenv("MAC", mac_to_str(rx.eh.ether_shost), 1); setenv("NETMASK", inet_ntoa(ipconf.mask), 1); status = system(args->tftpcmd); } if (!status && args->file_local) { if (!autoip) { status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); if (status < 0) { goto out; } else if (!status) { printf("IP address of %s has changed. Please assign a " "static ip to the interface.\n", args->intf); tx.msg.code = NMRP_C_CLOSE_REQ; break; } } if (verbosity) { printf("Using remote filename '%s'.\n", args->file_remote); } if (!strcmp(args->file_local, "-")) { printf("Uploading from stdin ... "); } else { printf("Uploading %s ... ", leafname(args->file_local)); } fflush(stdout); status = tftp_put(args); } if (!status) { printf("OK\nWaiting for remote to respond.\n"); upload_ok = 1; ethsock_set_timeout(sock, args->ul_timeout); tx.msg.code = NMRP_C_KEEP_ALIVE_REQ; expect = NMRP_C_NONE; } else if (status == -2) { expect = NMRP_C_TFTP_UL_REQ; } else { goto out; } break; case NMRP_C_KEEP_ALIVE_REQ: tx.msg.code = NMRP_C_KEEP_ALIVE_ACK; ethsock_set_timeout(sock, args->ul_timeout); printf("Received keep-alive request.\n"); break; case NMRP_C_CLOSE_REQ: tx.msg.code = NMRP_C_CLOSE_ACK; break; case NMRP_C_CLOSE_ACK: status = 0; goto out; default: fprintf(stderr, "Unknown message code 0x%02x!\n", rx.msg.code); msg_dump(&rx.msg, 0); } if (tx.msg.code != NMRP_C_NONE) { msg_hton(&tx.msg); if (pkt_send(sock, &tx) < 0) { perror("sendto"); goto out; } if (tx.msg.code == NMRP_C_CLOSE_REQ) { goto out; } } if (rx.msg.code == NMRP_C_CLOSE_REQ) { printf("Remote finished. Closing connection.\n"); break; } status = pkt_recv(sock, &rx); if (status) { if (status == 2) { fprintf(stderr, "Timeout while waiting for %s.\n", msg_code_str(expect)); } goto out; } ethsock_set_timeout(sock, args->rx_timeout); } while (1); status = 0; if (ulreqs) { printf("Reboot your device now.\n"); } else { printf("No upload request received.\n"); } out: signal(SIGINT, sigh_orig); gsock = NULL; ethsock_arp_del(sock, arpmac, &arpip); ethsock_ip_del(sock, &gundo); ethsock_close(sock); return status; }
/** Find devices on remote host. * Create new devices on local virtual bus. * \warning Function replaces global usb_busses variable from libusb. */ int usb_find_devices(void) { // Get remote fd Packet* pkt = pkt_claim(); int fd = session_get(); // Create buffer pkt_init(pkt, UsbFindDevices); pkt_send(pkt, fd); // Get number of changes int res = 0; Iterator it; if(pkt_recv(fd, pkt) > 0) { pkt_begin(pkt, &it); // Get return value res = iter_getint(&it); // Allocate virtualbus struct usb_bus vbus; vbus.next = __remote_bus; struct usb_bus* rbus = &vbus; // Get busses while(!iter_end(&it)) { // Evaluate if(it.type == StructureType) { iter_enter(&it); // Allocate bus if(rbus->next == NULL) { // Allocate next item struct usb_bus* nbus = malloc(sizeof(struct usb_bus)); memset(nbus, 0, sizeof(struct usb_bus)); rbus->next = nbus; nbus->prev = rbus; rbus = nbus; } else rbus = rbus->next; // Read dirname strcpy(rbus->dirname, iter_getstr(&it)); // Read location rbus->location = iter_getuint(&it); // Read devices struct usb_device vdev; vdev.next = rbus->devices; struct usb_device* dev = &vdev; while(it.type == SequenceType) { iter_enter(&it); // Initialize if(dev->next == NULL) { dev->next = malloc(sizeof(struct usb_device)); memset(dev->next, 0, sizeof(struct usb_device)); dev->next->bus = rbus; if(dev != &vdev) dev->next->prev = dev; if(rbus->devices == NULL) rbus->devices = dev->next; } dev = dev->next; // Read filename strcpy(dev->filename, iter_getstr(&it)); // Read devnum dev->devnum = iter_getuint(&it); // Read descriptor // Apply byte-order conversion for 16/32bit integers memcpy(&dev->descriptor, it.val, it.len); dev->descriptor.bcdUSB = ntohs(dev->descriptor.bcdUSB); dev->descriptor.idVendor = ntohs(dev->descriptor.idVendor); dev->descriptor.idProduct = ntohs(dev->descriptor.idProduct); dev->descriptor.bcdDevice = ntohs(dev->descriptor.bcdDevice); iter_next(&it); // Alloc configurations unsigned cfgid = 0, cfgnum = dev->descriptor.bNumConfigurations; dev->config = NULL; if(cfgnum > 0) { dev->config = malloc(cfgnum * sizeof(struct usb_config_descriptor)); memset(dev->config, 0, cfgnum * sizeof(struct usb_config_descriptor)); } // Read config while(it.type == RawType && cfgid < cfgnum) { struct usb_config_descriptor* cfg = &dev->config[cfgid]; ++cfgid; // Ensure struct under/overlap int szlen = sizeof(struct usb_config_descriptor); if(szlen > it.len) szlen = it.len; // Read config and apply byte-order conversion memcpy(cfg, it.val, szlen); cfg->wTotalLength = ntohs(cfg->wTotalLength); // Allocate interfaces cfg->interface = NULL; if(cfg->bNumInterfaces > 0) { cfg->interface = malloc(cfg->bNumInterfaces * sizeof(struct usb_interface)); } //! \test Implement usb_device extra interfaces - are they needed? cfg->extralen = 0; cfg->extra = NULL; iter_next(&it); // Load interfaces unsigned i, j, k; for(i = 0; i < cfg->bNumInterfaces; ++i) { struct usb_interface* iface = &cfg->interface[i]; // Read altsettings count iface->num_altsetting = iter_getint(&it); // Allocate altsettings if(iface->num_altsetting > 0) { iface->altsetting = malloc(iface->num_altsetting * sizeof(struct usb_interface_descriptor)); } // Load altsettings for(j = 0; j < iface->num_altsetting; ++j) { // Ensure struct under/overlap struct usb_interface_descriptor* as = &iface->altsetting[j]; int szlen = sizeof(struct usb_interface_descriptor); if(szlen > it.len) szlen = it.len; // Read altsettings - no conversions apply memcpy(as, it.val, szlen); iter_next(&it); // Allocate endpoints as->endpoint = NULL; if(as->bNumEndpoints > 0) { size_t epsize = as->bNumEndpoints * sizeof(struct usb_endpoint_descriptor); as->endpoint = malloc(epsize); memset(as->endpoint, 0, epsize); } // Load endpoints for(k = 0; k < as->bNumEndpoints; ++k) { struct usb_endpoint_descriptor* endpoint = &as->endpoint[k]; int szlen = sizeof(struct usb_endpoint_descriptor); if(szlen > it.len) szlen = it.len; // Read endpoint and apply conversion memcpy(endpoint, it.val, szlen); endpoint->wMaxPacketSize = ntohs(endpoint->wMaxPacketSize); iter_next(&it); // Null extra descriptors. endpoint->extralen = 0; endpoint->extra = NULL; } // Read extra interface descriptors as->extralen = as_int(it.val, it.len); iter_next(&it); if(as->extralen > 0){ as->extra = malloc(as->extralen); int szlen = as->extralen; if(szlen > it.len) szlen = it.len; memcpy(as->extra, it.val, szlen); iter_next(&it); } else as->extra = NULL; } } } //log_msg("Bus %s Device %s: ID %04x:%04x", rbus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct); } // Free unused devices while(dev->next != NULL) { struct usb_device* ddev = dev->next; debug_msg("deleting device %03d", ddev->devnum); dev->next = ddev->next; free(ddev); } } else { debug_msg("unexpected item identifier 0x%02x", it.type); iter_next(&it); } } // Deallocate unnecessary busses while(rbus->next != NULL) { debug_msg("deleting bus %03d", rbus->next->location); struct usb_bus* bus = rbus->next; rbus->next = bus->next; } // Save busses if(__remote_bus == NULL) { __orig_bus = usb_busses; debug_msg("overriding global usb_busses from %p to %p", usb_busses, vbus.next); } __remote_bus = vbus.next; usb_busses = __remote_bus; } // Return remote result pkt_release(); debug_msg("returned %d", res); return res; }