Transfering Large Files to Prime

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Calculators (and very old HP Computers) (https://www.hpmuseum.org/forum/forum-3.html)
+--- Forum: HP Prime (https://www.hpmuseum.org/forum/forum-5.html)
+--- Thread: Transfering Large Files to Prime (/thread-25185.html)



Transfering Large Files to Prime - t5-mini-high - 2026-06-24 06:22, edited 2026-06-26 11:30

Prime G1 only.

QuickTransfer uses the backdoor to hjiack the system's usb functionality, enabling large file tranfer without a system crash(oom).

Usage

QuickTransfer includes a server(QuickTransfer.hpappdir) and a client(QuickTransfer.exe).

1. Use HP Connectivity Kit to transfer QuickTransfer.hpappdir to your PrimeG1 first.

2. Open QuickTransfer app.

3. Use QuickTransfer.exe CLI:

  ping                          Test connectivity
  ls <pattern>                  List directory (e.g., ls "C:\DATA\*")
  get <remote> <local>          Download file
  put <local> <remote>          Upload file
  rm <remote>                  Delete file
  mkdir <remote>                Create directory
  info <remote>                Get file info

Note

Use Shift+ON to flush file buffers to avoid potential file loss.

Create a new xxx.hpappdir won't appear in Apps view until you reboot it(ON+Symb).

Requires backdoor to be installed.(Use BackdoorInstaller)

Prime G1 only.

QuickTransfer is written in C#, so you need to install .Net 8 first.here


See here for a better approach.


RE: QuickTransfer: Transfering Large Files between Windows and Prime - t5-mini-high - 2026-06-25 07:33

(2026-06-24, 22:54)parisse Wrote: Is there any pointer to the source code of the elf? Some functions I see inside like usb_send, usb_receive_callback,... would be useful to add USB support to UpsilonG1 (https://www.hpmuseum.org/forum/thread-25183.html). 
Thanks!

It uses BestaRTOS's USB functionality.(\\?\USB)
Code:
  if (g_vdev_table[handle].ends_with("USB")) {
    // ── USB Slave (Device) IOCTLs ──
    // S3C2416 USB Device Controller emulation
    switch (request) {
    case 4:
      // DeviceIoEnable: pull up USB connection, start descriptor handshake
      std::cout << "    +USB Slave: Enable (connect to host)\n";
      return 1;

    case 5:
      // DeviceIoDisable: disconnect / power down
      std::cout << "    +USB Slave: Disable (disconnect)\n";
      return 1;

    case 10:
      // DeviceIoChkwake: check wake/suspend status
      // Return 1 = awake, 0 = suspended
      std::cout << "    +USB Slave: ChkWake -> awake\n";
      return 1;

    case 256: {
      // Status query: is USB Slave connected to external host (PC)?
      // Return connection status in output buffer
      std::cout << "    +USB Slave: Status query -> connected\n";
      if (out && outlen >= 4) {
        *(uint32_t *)out = 1; // 1 = connected
      }
      if (retlen)
        *retlen = 4;
      return 1;
    }

    case 258:
      // USBDRV_IO_SET_REVCALLBACK / Bulk Out:
      // Send data from guest to host PC via named pipe bridge
      std::cout << "    +USB Slave: Bulk Out " << size << " bytes\n";
      if (usb_out_cb)
        usb_out_cb(in, size);
      return 1;

    case 259:
      // Set receive callback: guest registers function pointer for
      // async notification when host PC sends data to device
      std::cout << "    +USB Slave: Set IN callback -> 0x" << std::hex
                << (uint32_t)args->r2 << std::dec << "\n";
      usb_in_cb = args->r2;
      return 1;

    case 263:
      // Extended status / capability query
      return 0;

    default:
      std::cout << "    +USB Slave: unknown IOCTL " << request << "\n";
      return 1;
    }
  }

  if (g_vdev_table[handle].ends_with("USBHOST")) {
    // ── USB Host (OHCI) IOCTLs ──
    // S3C2416 OHCI Host Controller emulation
    switch (request) {
    case 4:
      // Enable host controller / root hub power
      std::cout << "    +USB Host: Enable (power on root hub)\n";
      return 1;

    case 5:
      // Disable host controller
      std::cout << "    +USB Host: Disable\n";
      return 1;

    case 256: {
      return 0;
    }

    case 257: {
      return 0;
    }

    case 258: {
      std::cout << "    +USB Host: SendData " << size << " bytes\n";
      if (usb_out_cb)
        usb_out_cb(in, size);
      return 1;
    }

    case 259: {
      std::cout << "    +USB Host: Set receive callback -> 0x" << std::hex
                << (uint32_t)args->r2 << std::dec << "\n";
      usb_in_cb = args->r2;
      return 1;
    }

    case 260: {
      // dword_30015318 + 1: status check (sub_300155A8 ? 2 : sub_3001307C)
      std::cout << "    +USB Host: Extended status check\n";
      return 1; // device present
    }

    case 261: {
      // dword_30015318 + 2: init_usb_host() re-init
      std::cout << "    +USB Host: Re-init host controller\n";
      return 1;
    }

    case 262: {
      // dword_30015318 + 3: sub_30018E54(1) - set device address
      std::cout << "    +USB Host: Set device address\n";
      return 1;
    }

    case 263: {
      // dword_30015318 + 4: return *off_30015330 (device address/speed)
      std::cout << "    +USB Host: Get device speed\n";
      return 0;
    }

    default:
      std::cout << "    +USB Host: unknown IOCTL " << request << "\n";
      return 1;
    }
  }
 


I'll upload both my ida database(ida9+) and the source code.(code shown above is my prime emulator impl)


RE: QuickTransfer: Transfering Large Files between Windows and Prime - parisse - 2026-06-25 12:25

Thank you, but I'm afraid it's much more complicated than what I can understand...
What about trying the Besta OS syscall  0x1024b USBMassStorageRun ? Is it not functional on the G1? Or does it expose something different from g1 drive c:?


RE: QuickTransfer: Transfering Large Files between Windows and Prime - parisse - 2026-06-26 10:58

USBMassStorageRun expects a callback as 1st argument. The 2nd arg is probably 0 if the callback is ignored, and 1 if it is called during the process. I tried with 0 as first arg, but it fails (there is probably a check for a non null callback).
Try this, while the G1 is connected:

typedef short (*usb_cb_t)(unsigned short , unsigned short);
extern "C" void USBMassStorageRun(usb_cb_t usb_cb,unsigned short u);

short usb_cb(unsigned short, unsigned short){
  return 0;
}
USBMassStorageRun(usb_cb,false);


RE: QuickTransfer: Transfering Large Files between Windows and Prime - t5-mini-high - 2026-06-26 11:19

This should be better than my original approach.

Code:
import ustruct as struct
import uio

class PrimeDebug:
    def __init__(self, filename="debug"):
        try:
            self.f = uio.FileIO("debug")
        except:
            self.f = open(filename, "rb")
        print("[+] Debug interface opened.")
    def close(self):
        if self.f: self.f.close()
    def set_addr(self, addr):
        cmd = struct.pack("<III", 0, addr, 0)
        self.f.write(cmd)
    def read_mem(self, addr, size):
        self.set_addr(addr)
        return self.f.read(size)
    def write_mem(self, addr, val):
        cmd = struct.pack("<III", 1, addr, val)
        self.f.write(cmd)
    def call(self, func_addr, *args):
        arg_count = len(args)
        buf = bytearray(12 + (arg_count * 4))
        struct.pack_into("<III", buf, 0, 2, func_addr, arg_count)
        offset = 12
        for arg in args:
            struct.pack_into("<I", buf, offset, arg)
            offset += 4
        self.f.write(buf)
        return struct.unpack_from("<I", buf, 0)[0]
class CodeLoader:
    ADDR_MALLOC = 0x307FBF40
    ADDR_FREE   = 0x307FBF64
    ADDR_ICACHE = 0x3007E7E4
    def __init__(self, debug_interface):
        self.dbg = debug_interface
        self.allocations = []
    def load(self, machine_code_bytes):
        length = len(machine_code_bytes)
        if length % 4 != 0:
            machine_code_bytes += b'\x00' * (4 - (length % 4))
            length = len(machine_code_bytes)
       
        addr = self.dbg.call(self.ADDR_MALLOC, length)
        if addr == 0:
            print("[-] Malloc failed!")
            return None
       
        self.allocations.append(addr)
        for i in range(0, length, 4):
            val = struct.unpack("<I", machine_code_bytes[i:i+4])[0]
            self.dbg.write_mem(addr + i, val)
       
        self.dbg.call(self.ADDR_ICACHE)
        return addr
    def free(self, addr):
        if addr in self.allocations:
            self.dbg.call(self.ADDR_FREE, addr)
            self.allocations.remove(addr)

CALLBACK_STUB = bytes([
    0x00, 0x20,  # MOVS r0, #0
    0x70, 0x47,  # BX   lr
])
USB_MASS_STORAGE_RUN = 0x300135AC
dbg = PrimeDebug()
loader = CodeLoader(dbg)
cb_addr = loader.load(CALLBACK_STUB)
if cb_addr is None:
    pass
else:
    cb_thumb_ptr = cb_addr | 1
    result = dbg.call(USB_MASS_STORAGE_RUN, cb_thumb_ptr, 0)
    loader.free(cb_addr)