void rpc_send_bulk_gather(const void *in, uint32_t len, int32_t stride, uint32_t n)
{
   if (in && len) {
      CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();

      merge_flush(thread);

      if (len == stride) {
         /* hopefully should be the common case */
         send_bulk(thread, in, n * len);
      } else {
         check_workspace(n * len);
         rpc_gather(workspace, in, len, stride, n);
         send_bulk(thread, workspace, n * len);
      }
   }
}
static void msd()
{
#if 1
    unsigned InEndPt = 1;
    unsigned OutEndPt = 1;
#else
    unsigned InEndPt = 1;
    unsigned OutEndPt = 2;
#endif
    unsigned char abBuf[512];
    int i;

//    set_config(1); - the culprit
    set_interface(0, 0);

#if 0
    /* Send an Get Max LUN request */
    abBuf[0] = 0;
    if (doctrl(VUSB_DIR_TO_HOST | VUSB_REQ_CLASS | VUSB_TO_INTERFACE,
               0xfe /* max lun */, 0, 1, 1, abBuf, "get max lun") >= 0)
        printf("max luns: %d\n",  abBuf[0]);
#endif

    for (i = 0; i < 3; i++)
    {
        printf("i=%d\n", i);

        /* Send an INQUIRY command to ep 2 */
        memset(abBuf, 0, sizeof(abBuf));
        memcpy(abBuf, "USBC", 4);
        *(uint32_t *)(&abBuf[4]) = 0x12330984 ;
        //abBuf[8]    = 0x08;
        abBuf[8]    = 0x24;
        abBuf[0xc]  = 0x80;
        abBuf[0xe]  = 0x06; /* cmd length */
        abBuf[0x0f] = 0x12; /* cmd - INQUIRY */
        abBuf[0x13] = 0x24;

        hex(abBuf, 31, "intquery req");
        if (send_bulk(OutEndPt, abBuf, 31) < 0)
            return;
        //usleep(15000);

        /* read result */
        memset(abBuf, 0, sizeof(abBuf));
    //printf("recv..\n");
        int cb = recv_bulk(InEndPt, abBuf, 36);
        hex(abBuf, cb, "inquiry result");

        /* sense? */
        memset(abBuf, 0, sizeof(abBuf));
        cb = recv_bulk(InEndPt, abBuf, 36);
        hex(abBuf, cb, "inquiry sense?");
        usleep(150000);
    }
}
void rpc_send_bulk(const void *in, uint32_t len)
{
    if (in && len) {
        CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();

        merge_flush(thread);

        send_bulk(thread, in, len);
    }
}
void palm(void)
{
//    set_config(1); //skip this
//    reset_ep(6);

    /* This seems to be some kind of 'identify device' request. */
    uint8_t abVendor[0x14] = {0};
    int cb = doctrl(VUSB_DIR_TO_HOST | VUSB_REQ_VENDOR | VUSB_TO_ENDPOINT,
                    0x04, 0, 0, 0x14, abVendor, "vendor req");
    hex(abVendor, cb, "palm vendor req");

    /* read from ep 6. */
    uint8_t abBuf[512];
    memset(abBuf, 0, sizeof(abBuf));
    cb = recv_bulk(6, abBuf, 6);
    hex(abBuf, cb, "bulk 1");

    /* read from ep 6. */
    memset(abBuf, 0, sizeof(abBuf));
    cb = recv_bulk(6, abBuf, 22);
    hex(abBuf, cb, "bulk 2");

#if 0
    /* write to ep 6 */
    memset(abBuf, 0, sizeof(abBuf));
    abBuf[0] = 1;
    abBuf[1] = 2;
    abBuf[5] = 0x32;
    if (send_bulk(7, abBuf, 6) < 0)
        return;

    memset(abBuf, 0, sizeof(abBuf));
    abBuf[0] = 0x12;
    abBuf[1] = 1;
    if (send_bulk(7, abBuf, 8) < 0)
        return;

    memset(abBuf, 0, sizeof(abBuf));
    abBuf[1] = 0x20;
    abBuf[6] = 0x24;
    if (send_bulk(7, abBuf, 6) < 0)
        return;

    memset(abBuf, 0, sizeof(abBuf));
    abBuf[0] = 0xff;
    abBuf[1] = 0xff;
    abBuf[2] = 0xff;
    abBuf[3] = 0xff;
    abBuf[4] = 0x3c;
    abBuf[6] = 0x3c;
    abBuf[0x0f] = 1;
    abBuf[0x11] = 0x10;
    abBuf[0x15] = 0x10;
    abBuf[0x18] = 0x3c;
    abBuf[0x1a] = 0x3c;
    if (send_bulk(7, abBuf, 0x24) < 0)
        return;

    /* read from ep 6 */
    memset(abBuf, 0, sizeof(abBuf));
    cb = recv_bulk(6, abBuf, 64);
    hex(abBuf, cb, "bulk 3");

    /* read from ep 6. */
    memset(abBuf, 0, sizeof(abBuf));
    cb = recv_bulk(6, abBuf, 50);
    hex(abBuf, cb, "bulk 4");
#endif
}