Raw printing directly to a USB printer, bypassing Windows spooler

后端 未结 4 1098
情书的邮戳
情书的邮戳 2020-12-11 01:51

I\'m experimenting with a Zebra TTP8200 thermal printer. For my application I need to print plotter type traces continuously until the user hits a stop button. I\'ve had a p

4条回答
  •  天涯浪人
    2020-12-11 02:16

    Thanks for the comments.

    After some more digging around, I found this interesting article on using Windows printer functions provided by usbprint.sys. With a bit of hacking the sample code there seemed to work. I think I'll take this route.

    There is the final code given in the article:

    /* Code to find the device path for a usbprint.sys controlled
    * usb printer and print to it
    */
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    /* This define is required so that the GUID_DEVINTERFACE_USBPRINT variable is
     * declared an initialised as a static locally, since windows does not include it
     * in any of its libraries
     */
    
    #define SS_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    static const GUID name \
    = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
    
    SS_DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT, 0x28d78fad, 0x5a12, 0x11D1, 0xae,
                   0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);
    
    void SomeFunctionToWriteToUSB()
    {
      HDEVINFO devs;
      DWORD devcount;
      SP_DEVINFO_DATA devinfo;
      SP_DEVICE_INTERFACE_DATA devinterface;
      DWORD size;
      GUID intfce;
      PSP_DEVICE_INTERFACE_DETAIL_DATA interface_detail;
    
      intfce = GUID_DEVINTERFACE_USBPRINT;
      devs = SetupDiGetClassDevs(&intfce, 0, 0, DIGCF_PRESENT |
                                 DIGCF_DEVICEINTERFACE);
      if (devs == INVALID_HANDLE_VALUE) {
        return;
      }
      devcount = 0;
      devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
      while (SetupDiEnumDeviceInterfaces(devs, 0, &intfce, devcount, &devinterface)) {
        /* The following buffers would normally be malloced to he correct size
         * but here we just declare them as large stack variables
         * to make the code more readable
         */
        char driverkey[2048];
        char interfacename[2048];
        char location[2048];
        char description[2048];
    
        /* If this is not the device we want, we would normally continue onto the
         * next one or so something like
         * if (!required_device) continue; would be added here
         */
        devcount++;
        size = 0;
        /* See how large a buffer we require for the device interface details */
        SetupDiGetDeviceInterfaceDetail(devs, &devinterface, 0, 0, &size, 0);
        devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
        interface_detail = calloc(1, size);
        if (interface_detail) {
          interface_detail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
          devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
          if (!SetupDiGetDeviceInterfaceDetail(devs, &devinterface, interface_detail,
                                               size, 0, &devinfo)) {
        free(interface_detail);
        SetupDiDestroyDeviceInfoList(devs);
        return;
          }
          /* Make a copy of the device path for later use */
          strcpy(interfacename, interface_detail->DevicePath);
          free(interface_detail);
          /* And now fetch some useful registry entries */
          size = sizeof(driverkey);
          driverkey[0] = 0;
          if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo, SPDRP_DRIVER, &dataType,
                                                (LPBYTE)driverkey, size, 0)) {
        SetupDiDestroyDeviceInfoList(devs);
        return;
          }
          size = sizeof(location);
          location[0] = 0;
          if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo,
                                                SPDRP_LOCATION_INFORMATION, &dataType,
                                                (LPBYTE)location, size, 0)) {
        SetupDiDestroyDeviceInfoList(devs);
        return;
          }
          usbHandle = CreateFile(interfacename, GENERIC_WRITE, FILE_SHARE_READ,
                     NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL |
                     FILE_FLAG_SEQUENTIAL_SCAN, NULL);
          if (usbHandle != INVALID_HANDLE_VALUE) {
        /* Now perform all the writing to the device ie.
         * while (some condition) WriteFile(usbHandle, buf, size, &bytes_written);
         */
        CloseHandle(usbHandle);
          }
        }
      }
      SetupDiDestroyDeviceInfoList(devs);
    }
    

    Thanks again for the suggestions.

提交回复
热议问题