2

I need to print a BMP file to USB printer using commands.

C++ signature is

USB_API BOOL Usb_WritePort(BOOL bUseBulkEndp, LPCVOID lpBuffer, DWORD dwNumberOfBytesToWrite, 

LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);

This is my C# signature

[DllImport("usbRtb.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern Boolean Usb_WritePort(bool bUseBulkEndp, IntPtr lpBuffer, UInt32 nNumberOfBytesToWrite,
          out UInt32 lpNumberOfBytesWritten, [In] ref NativeOverlapped lpOverlapped);

I tried

 update = Usb_UpdateConnection(0, ref out1, ref out2);
        char[] files = System.Text.Encoding.ASCII.GetString(File.ReadAllBytes(@"D:\\mailman.BMP")).ToCharArray();
        update = Usb_UpdateConnection(0, ref out1, ref out2);
        byte[] pr = Encoding.BigEndianUnicode.GetBytes(files);
        intpt = Marshal.StringToCoTaskMemAnsi("\x1F\x42\x4D\x50" + ASCIIEncoding.ASCII.GetString(pr));
        count = (UInt32)pr.Count() + 4;
        var read = Usb_WritePort(true, intpt, count, out written, ref natOverlap0);

Attaching printer manual BMP image print command section:enter image description here

C++ SDK Documentation: Usb_WritePort

Syntax:

BOOL Usb_WritePort (BOOL                    bUseBulkEndp,
                                     LPCVOID              lpBuffer, 
                                     DWORD                dwNumberOfBytesToWrite, 
                                     LPDWORD            lpNumberOfBytesWritten, 
                                     LPOVERLAPPED lpOverlapped);

Purpose: Writes data to the currently selected device over the specified output endpoint. Connection needs to have first been established with Usb_UpdateConnection() API. Operation is similar to using WriteFile() in both synchronous and asynchronous modes with overlapped structure.

Parameters:

bUseBulkEndp [in] Set parameter to TRUE to write data over BULK OUT endpoint, to FALSE to write over INTERRUPT OUT endpoint

lpBuffer [in] Pointer to the buffer that contains the data to write to the device.

dwNumberOfBytesToWrite [in] Number of bytes to write to the device. This number must be less than or equal to the size, in bytes, of data buffer

lpNumberOfBytesWritten [out] Pointer to the variable that receives the number of bytes effectively written to the device.

lpOverlapped [in/out] Optional pointer to an OVERLAPPED structure, which is used for asynchronous operations. If this parameter is specified, Usb_WritePort immediately returns, and the event is signaled when the operation is complete.

Return value: TRUE if write operation succeeds, FALSE otherwise. If FALSE, user may call GetLastError() to get additional information

Printer prints nothing. Please help me to solve this.

Frebin Francis
  • 1,905
  • 1
  • 11
  • 19

1 Answers1

3
    Marshal.StringToCoTaskMemAnsi("\x1F\x42\x4D\x50" + ASCIIEncoding.ASCII.GetString(pr));

Your code is not close to correct, using ASCIIEncoding is quite wrong. The bitmap contains byte values that cannot be represented in ASCII. First thing you need to do is change the pinvoke declaration, the 2nd argument needs to be byte[] and you would be wise to avoid overlapped I/O since that requires a lot more pinvoke. So:

    [DllImport("usbRtb.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern Boolean Usb_WritePort(
        bool bUseBulkEndp, 
        byte[] lpBuffer, 
        int nNumberOfBytesToWrite,
        out int lpNumberOfBytesWritten, 
        IntPtr lpOverlapped
    );

Next thing you need to do is pay close attention to the actual bitmap. The manual demands that this is a monochrome bitmap, that is not so easy to come by these days. But you can still create one with MSPaint, start with something very small and use File + Save As, change the "Save as type" setting to "Monochrome Bitmap (*.bmp, *.dib)".

Next you need to create the proper byte[] before you call the function. It needs to resemble this:

    using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) {
        byte[] inpt = new byte[fs.Length + 1];
        inpt[0] = 0x1f;
        fs.Read(inpt, 1, (int)fs.Length);
        int written;
        bool ok = Usb_WritePort(true, inpt, inpt.Length, out written, IntPtr.Zero);
        if (!ok || written != inpt.Length) throw new Exception("USB write failed");
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536