//
// CONFIG_ATH9...
// apt install firmware-ath9k-htc
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <assert.h>

#define W_PRODUCT 1
#define W_REG 2
#define W_EEPROM 4
#define W_PKT 8
#define W_HDR 16

int which = W_PKT;

unsigned int vendor = 0x0cf3; // Atheros
unsigned int product = 0x9271;

unsigned long aa[] = {
0x20400003e70ull,
0x21000000070ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
};
int aai;

static inline unsigned long real_symx() {
  return aa[aai++];
}

static int started = 0;
static int sai = 0;
static unsigned long symx() {
#define NSYM 256
  static unsigned long sa[NSYM];
  if(started == 0){
    started = 1;
    usleep(200000);
    for(int i = 0; i < NSYM; i++){
      sa[i] = real_symx();
    }
  }
  if(sai >= NSYM){
    return 0;
  }
  return sa[sai++];
}

struct op_common {
  unsigned short version;
  unsigned short code;
  unsigned int status;
};

struct usbip_usb_device {
	char path[256];
	char busid[32];

	uint32_t busnum;
	uint32_t devnum;
	uint32_t speed;

	uint16_t idVendor;
	uint16_t idProduct;
	uint16_t bcdDevice;

	uint8_t bDeviceClass;
	uint8_t bDeviceSubClass;
	uint8_t bDeviceProtocol;
	uint8_t bConfigurationValue;
	uint8_t bNumConfigurations;
	uint8_t bNumInterfaces;
} __attribute__((packed));

struct usbip_header_basic {
  unsigned int command;
  unsigned int seqnum;
  unsigned int devid;
  unsigned int direction;
  unsigned int ep;
};

struct usbip_header_cmd_submit {
  unsigned int transfer_flags;
  int transfer_buffer_length;
  int start_frame;
  int number_of_packets;
  int interval;
  unsigned char setup[8];
};

struct usbip_header_ret_submit {
  int status;
  int actual_length;
  int start_frame;
  int number_of_packets;
  int error_count;
};

int
readable(int fd)
{
  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(fd, &readfds);
  struct timeval tv;
  tv.tv_sec = 10;
  tv.tv_usec = 0;
  int ss = select(fd + 1, &readfds, (fd_set*)0, (fd_set*)0, &tv);
  return FD_ISSET(fd, &readfds);
}

int
readn(int fd, void *xbuf, int n)
{
  char *buf = xbuf;
  int got = 0;
  while(got < n){
    if(readable(fd) == 0){
      return -1;
    }
    int cc = read(fd, buf+got, n-got);
    if(cc <= 0){
      perror("usbip0: read");
      return -1;
    }
    got += cc;
  }
  return got;
}

void
mkif(char **xp, int num, int alt, int eps, int cl, int subcl, int proto, int iff)
{
  char *p = *xp;

  // usb_interface_descriptor
  *p++ = 9; // bLength
  *p++ = 4; // bDescriptorType USB_DT_INTERFACE
  *p++ = num; // bInterfaceNumber
  *p++ = alt; // bAlternateSetting
  *p++ = eps; // bNumEndpoints
  *p++ = cl; // bInterfaceClass
  *p++ = subcl; // bInterfaceSubClass
  *p++ = proto; // bInterfaceProtocol
  *p++ = iff; // iInterface

  *xp = p;
}

void
mkad(char **xp, int type, int subtype)
{
  char *p = *xp;

  // Additional Descriptor

  *p++ = 0; // bLength (filled in later)
  *p++ = type; // bDescriptorType
  *p++ = subtype; // bDescriptorSubtype
  
  if(type == 36 && subtype == 1){
    // AS_GENERAL
    *p++ = 1; // bTerminalLink
    *p++ = 1; // bDelay
    *p++ = 1; // wFormatTag PCM
    p++;
  } else if(type == 36 && subtype == 2){
    // FORMAT_TYPE
    *p++ = 1; // bFormatType
    *p++ = 2; // bNrChannels
    *p++ = 3; // bSubframeSize
    *p++ = 24; // bBitResolution
    *p++ = 2; // bSamFreqType 
    *p++ = 2; // bSamFreqType 
    p += 5;
  } else {
    *p++ = 0; // bcdADC
    *p++ = 1;
    *(short*)p = 0x5f; // wTotalLength
    p += 2;
    *p++ = 2; // bInCollection
    *p++ = 1; // baInterfaceNr(0)
    *p++ = 2; // baInterfaceNr(1)
  }

  *(*xp) = p - (*xp); // bLength

  *xp = p;
}

void
mkadx(char **xp, int type, int subtype, int len, int a[])
{
  char *p = *xp;

  // Additional Descriptor

  *p++ = 0; // bLength (filled in later)
  *p++ = type; // bDescriptorType
  *p++ = subtype; // bDescriptorSubtype

  for(int i = 0; i < len - 3; i++)
    *p++ = a[i];

  *(*xp) = p - (*xp); // bLength
  *xp = p;
}

void
mkep(char **xp, int epa, int attr, int maxp)
{
  char *p = *xp;

  // usb_endpoint_descriptor
  *p++ = 9;
  *p++ = 5; // bDescriptorType USB_DT_ENDPOINT
  *p++ = epa; // bEndpointAddress
  *p++ = attr; // bmAttributes
  *(short*)p = maxp; // wMaxPacketSize
  p += 2;
  *p++ = 7; // bInterval
  p += 2; // ???

  *xp = p;
}

int
main(int argc, char *argv[])
{
  struct rlimit r;
  r.rlim_cur = r.rlim_max = 0;
  setrlimit(RLIMIT_CORE, &r);

  int port = 3240;
  int s, yes = 1;
  struct sockaddr_in sin;

  system("echo 0 > /sys/module/usbip_core/parameters/usbip_debug_flag");
  //system("echo 4294967295 > /sys/module/usbip_core/parameters/usbip_debug_flag");

  system("killall usbip");
  sleep(1);

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port = htons(port);

  s = socket(AF_INET, SOCK_STREAM, 0);
  if(s < 0){
    perror("socket");
    exit(1);
  }

  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

  if(bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0){
    perror("usbxxx: bind");
    exit(1);
  }

  if(listen(s, 3000) < 0){
    perror("usbxxx: listen");
    exit(1);
  }

  system("usbip/src/usbip attach -r 127.0.0.1 -b 1-1 &");
  sleep(2);
  sync();
  sleep(1);

  int s1;
  unsigned sinlen = sizeof(sin);
  s1 = accept(s, (struct sockaddr *) &sin, &sinlen);
  if(s1 < 0){
    perror("accept");
    exit(1);
  }
  close(s);
  
  struct op_common op;
  
  // OP_REQ_IMPORT
  readn(s1, &op, sizeof(op));
  
  char busid[32];
  readn(s1, busid, sizeof(busid));
  
  op.code = htons(0x03); // OP_REP_IMPORT
  op.status = htonl(0); // ST_OK
  
  write(s1, &op, sizeof(op));
  
  struct usbip_usb_device uud;
  memset(&uud, 0, sizeof(uud));
  strcpy(uud.busid, busid);
  //uud.speed = htonl(2); // USB_SPEED_FULL
  uud.speed = htonl(3); // USB_SPEED_HIGH
  //uud.speed = htonl(5); // USB_SPEED_SUPER
  
  write(s1, &uud, sizeof(uud));
  
  // now talking to the kernel

  int cmdno = 0;

  if(fork() == 0){
    close(s1);
    while(1){
      sleep(1);
      if(system("ifconfig -a | grep wlan2") == 0){
        system("ifconfig wlan2 1.2.3.4 up");
        system("ifconfig wlan2");
        exit(0);
      }
    }
    exit(0);
  }

  if(fork() == 0){
    close(s1);
    while(1){
      sleep(1);
      if(system("ifconfig -a | grep wlx020200000000") == 0){
        system("ifconfig wlx020200000000 1.2.3.4 up");
        system("ifconfig wlx020200000000");
        exit(0);
      }
    }
    exit(0);
  }
  
  if(which & W_PRODUCT){
    product ^= symx();
  }

  int done = 0;
  int can_tx = 0;

#define NCMD 10240
  char *cmds[NCMD];
  int cmdw = 0;
  int cmdr = 0;
  
  while(done == 0){
    struct usbip_header_basic ibh;
    //sync(); // don't sync() -- deadlock.
    if(readn(s1, &ibh, sizeof(ibh)) < 0)
      break;

    if(ntohl(ibh.command) == 1){
      // USBIP_CMD_SUBMIT
      struct usbip_header_cmd_submit cs;
      memset(&cs, 0, sizeof(cs));
      if(readn(s1, &cs, sizeof(cs)) < 0)
        break;
      
      int translen = ntohl(cs.transfer_buffer_length);
      unsigned int ep = ntohl(ibh.ep);

      if(ibh.direction == 0){
        char ibuf[4096];
        assert(translen <= sizeof(ibuf));
        if(readn(s1, ibuf, translen) < 0)
          break;

        if(ep == 4){
          if(cmdw < NCMD){
            cmds[cmdw] = malloc(64);
            memcpy(cmds[cmdw], ibuf, 64);
            cmdw += 1;
          }
        }
      
        struct usbip_header_basic obh;
        memset(&obh, 0, sizeof(obh));
        obh.command = htonl(3); // USBIP_RET_SUBMIT
        obh.seqnum = ibh.seqnum;
        obh.devid = ibh.devid;
        obh.direction = htonl(!ntohl(ibh.direction));
        obh.ep = ibh.ep;
        write(s1, &obh, sizeof(obh));
        
        char rsbuf[sizeof(cs)];
        memset(rsbuf, 0, sizeof(rsbuf));
        struct usbip_header_ret_submit *rs = (void*)rsbuf;
        rs->actual_length = htonl(translen);
        write(s1, rs, sizeof(rsbuf));
      
      } else {
        char obuf[20480];
        if(translen > sizeof(obuf)){
          break;
        }
        memset(obuf, 0, sizeof(obuf));
        char *p = obuf;
        if(cs.setup[1] == 0x06){
          // USB_REQ_GET_DESCRIPTOR
          if(cs.setup[0] == 0x80 && cs.setup[3] == 1){
            // USB_DT_DEVICE
            // struct usb_device_descriptor
            obuf[0] = 18; // bLength
            obuf[1] = 1; // bDescriptorType = USB_DT_DEVICE
            obuf[2] = 0x20; // bcdUSB
            obuf[3] = 0x03; // bcdUSB
            obuf[4] = 0; // bDeviceClass
            obuf[5] = 0; // bDeviceSubClass
            obuf[6] = 0; // bDeviceProtocol
            obuf[7] = 64; // bMaxPacketSize0
            *(short*)(obuf+8) = vendor; // idVendor
            *(short*)(obuf+10) = product; // idProduct 
            obuf[12] = 0; // bcdDevice
            obuf[13] = 1; // bcdDevice
            obuf[14] = 2; // iManufacturer
            obuf[15] = 3; // iProduct
            obuf[16] = 1; // iSerial
            obuf[17] = 1; // bNumConfigurations
          } else if(cs.setup[0] == 0x80 && cs.setup[3] == 2){
            // USB_DT_CONFIG
            // struct usb_config_descriptor
            *p++ = 9; // bLength
            *p++ = 2; // USB_DT_CONFIG
            short *lenp = (short*) p;
            *(short*)p = 9 + 4*9 + 15*10 + 2*7; // wTotalLength
            p += 2;
            *p++ = 1; // bNumInterfaces
            *p++ = 1; // bConfigurationValue
            *p++ = 0; // iConfiguration
            *p++ = 0x80; // bmAttributes
            *p++ = 1; // bMaxPower
        
            // mkif(&p, num, alt, eps, cl, subcl, proto, iff)

            mkif(&p, 0, 0, 8, 0xff, 0xff, 0xff, 0);
            mkep(&p, 0x01, 0x02, 0x0200);
            mkep(&p, 0x82, 0x02, 0x0200);
            mkep(&p, 0x83, 0x03, 0x0200);
            mkep(&p, 0x04, 0x03, 0x0200);
            mkep(&p, 0x05, 0x02, 0x0200);
            mkep(&p, 0x86, 0x02, 0x0200);
            mkep(&p, 0x87, 0x03, 0x0200);
            mkep(&p, 0x08, 0x03, 0x0200);
            
            assert(p - obuf <= sizeof(obuf));
            *lenp = p - obuf;

          } else if(cs.setup[0] == 0x80 && cs.setup[3] == 0x0f){
            // USB_DT_BOS
            // struct usb_bos_descriptor
            *p++ = 5; // bLength
            *p++ = 15;
            *(short*)p = 0x002a; // wTotalLength
            p += 2;
            *p++ = 3; // bNumDeviceCaps
            // usb_ext_cap_descriptor
            *p++ = 7; // bLength
            *p++ = 16; // bDescriptorType
            *p++ = 2; // bDevCapabilityType
            *(int*)p = 0x0000f41e; // bmAttributes
            p += 4;
            // usb_ss_cap_descriptor
            *p++ = 10; // bLength
            *p++ = 16; // bDescriptorType
            *p++ = 3; // bDevCapabilityType
            *p++ = 0; // bmAttributes
            *(short*)p = 0xe; // wSpeedsSupported
            p += 2;
            *p++ = 1; // bFunctionalitySupport
            *p++ = 10; // bU1devExitLat
            *(short*)p = 2047; // bU2DevExitLat
            p += 2;
            // usb_ssp_cap_descriptor
            *p++ = 20; // bLength
            *p++ = 16; // bDescriptorType
            *p++ = 10; // bDevCapabilityType
            *p++ = 0; // bReserved
            *(int*)p = 0; // bmAttributes
            p += 4;
            *(short*)p = 1; // bFunctionalitySupport
            p += 2;
            p += 2; // wReserved
            *(int*)p = 0x000a4030;
            p += 4;
            *(int*)p = 0x000a40b0;
            p += 4;
          } else if(cs.setup[0] == 0x80 && cs.setup[3] == 3){
            // USB_DT_STRING
            *p++ = 6; // length
            *p++ = 3; // descriptor type
            *p++ = 'a';
            *p++ = 'b';
            *p++ = 'c';
            *p++ = 'd';
          }
        }

        unsigned char *ibuf = cs.setup;
        
        if(ep == 0x03){
          // asking for response to a previous ep=04 command/request
          // ath9k_hif_usb_reg_in_cb
          // ath9k_htc_rx_msg
          // struct htc_frame_hdr
          static int nth;
          if(nth == 0){
            // driver expects an unsolicited READY
            // htc_process_target_rdy
            *(short*)(obuf+8) = htons(1); // HTC_MSG_READY_ID
          } else if(cmdr < cmdw){
            // a command is waiting to be answered

            char *cmd = cmds[cmdr];
            memcpy(obuf, cmd, 64); // ???

            if(cmd[0] == 0){
              // htc_msg
              int msg_id = ntohs(*(short*)(cmd+8));
              if(msg_id == 2){
                // connect
                *(short*)(obuf+8) = htons(3);
                *(short*)(obuf+10) = htons((1<<8)|0); // service_id
                *(short*)(obuf+12) = htons(4); // endpoint_id
              } else if(msg_id == 5){
                // pipe
                *(short*)(obuf+8) = htons(6);
              }
              if(which & W_REG){
                *(long*)(obuf+8) ^= symx();
              }
            } else if(cmd[0] == 4){
              // wmi_cmd
              int command_id = ntohs(*(short*)(cmd+8));
              if(command_id == 20){
                // WMI_REG_READ_CMDID
                int reg = ntohs(*(short*)(cmd+14));
                memset(obuf+12, 0, 128); // default, esp for multi-read
                if(reg == 0x4020){
                  // REG_READ AR_SREV(ah) 0x4020
                  *(int*)(obuf+12) = htonl(0x00ff | (0x40 << 12));
                } else if(reg == 0x7044){
                  // AR_RTC_STATUS
                  *(int*)(obuf+12) = htonl(0x2); // AR_RTC_STATUS_ON
                } else if(reg == 0x407c){
                  *(int*)(obuf+12) = htonl(0xa55a); // AR_5416_EEPROM_MAGIC
                } else if(reg == 0x2400){
                  // start of eeprom
                  *(short*)(obuf+14) = htons(4); // length
                  *(short*)(obuf+18) = htons(0xffff ^ 4); // checksum
                  *(short*)(obuf+22) = htons((14 << 12) + 2); // version
                  *(short*)(obuf+26) = htons(0x0003); // opCapFlags
                  *(short*)(obuf+38) = htons(0x0202); // macAddr
                }
                if(reg < 0x2400 || (reg > 0x3d60 && reg < 0x8814) || (reg > 0x97f4)){
                  if(which & W_REG){
                    *(long*)(obuf+12) ^= symx();
                  }
                } else if(reg >= 0x2400 && reg <= 0x3d60){
                  if(which & W_EEPROM){
                    *(long*)(obuf+12) ^= symx();
                    *(long*)(obuf+20) ^= symx();
                    *(long*)(obuf+28) ^= symx();
                    *(long*)(obuf+36) ^= symx();
                  }
                } else {
                  // otherwise it's crypto key reset 0x8814 .. 0x97f4
                }
              } else if(command_id == 21){
                // WMI_REG_WRITE_CMDID
                int reg = ntohs(*(short*)(cmd+14));
              } else if(command_id == 32){
                // WMI_REG_RMW_CMDID read-modify-write
              } else if(command_id == 3){
                // WMI_GET_FW_VERSION
                *(short*)(obuf+12) = htons(1); // major
                *(short*)(obuf+14) = htons(3); // minor
                if(which & W_REG){
                  *(long*)(obuf+12) ^= symx();
                }
              } else if(command_id == 5){
                // WMI_ENABLE_INTR_CMDID
                // ifconfig has enabled the interface
                can_tx = 1;
              } else {
              }
            }

            if(which & W_HDR){
              *(long *)obuf ^= symx();
            }

            cmdr++;
          } else {
            translen = 0;
          }

          nth++;
        }
        
        if(ep == 0x02){
          // asking for a packet
          // ath9k_hif_usb_rx_cb
          if(can_tx){
            static int nth = 0;
            printf("sending packet!!!\n");
            usleep(100000);
            if(nth >= 3)
              done = 1;
            translen = 64;
            *(short*)(obuf+2) = 0x4e00; // ATH_USB_RX_STREAM_MODE_TAG
            if(which & W_PKT){
              for(int i = 0; i < translen; i += 8){
                *(long*)(obuf+i) ^= symx();
              }
            }
            nth++;
          } else {
            translen = 0;
          }
        }
      
        struct usbip_header_basic obh;
        memset(&obh, 0, sizeof(obh));
        obh.command = htonl(3); // USBIP_RET_SUBMIT
        obh.seqnum = ibh.seqnum;
        obh.devid = ibh.devid;
        obh.direction = htonl(!ntohl(ibh.direction));
        obh.ep = ibh.ep;
        write(s1, &obh, sizeof(obh));
        
        char rsbuf[sizeof(cs)];
        memset(rsbuf, 0, sizeof(rsbuf));
        struct usbip_header_ret_submit *rs = (void*)rsbuf;
        rs->actual_length = htonl(translen);
        write(s1, rs, sizeof(rsbuf));

        write(s1, obuf, translen);
      }
    } else if(ntohl(ibh.command) == 2){
      // USBIP_CMD_UNLINK
      // struct usbip_header_cmd_unlink uh;
      char buf[sizeof(struct usbip_header_cmd_submit)];
      memset(buf, 0, sizeof(buf));
      if(readn(s1, buf, sizeof(buf)) < 0)
        break;
      unsigned int uh = *(int*)buf;;
      
      struct usbip_header_basic obh;
      memset(&obh, 0, sizeof(obh));
      obh.command = htonl(4); // USBIP_RET_UNLINK
      obh.seqnum = ibh.seqnum;
      obh.devid = ibh.devid;
      obh.direction = htonl(!ntohl(ibh.direction));
      obh.ep = ibh.ep;
      write(s1, &obh, sizeof(obh));

      char rsbuf[sizeof(struct usbip_header_cmd_submit)];
      memset(rsbuf, 0, sizeof(rsbuf));
      write(s1, rsbuf, sizeof(rsbuf));
    }

    cmdno += 1;
  }

  sleep(2);
  close(s1);
  sleep(2);
}
