segatools/hooklib/printer.c

2381 lines
68 KiB
C

/*
Sinfonia CHC-C3XX Printer emulator
Credits:
c310emu (rakisaionji)
segatools-kancolle (OLEG)
c310emu (doremi)
*/
#include "hooklib/printer.h"
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "hook/table.h"
#include "hooklib/dll.h"
#include "hooklib/uart.h"
#include "util/dprintf.h"
#include "util/dump.h"
// #define IMAGE_SIZE 0x24FC00
#define IMAGE_SIZE 0x1F0800
#define HOLO_SIZE 0xC5400
static const int8_t idNumber = 0x01;
static uint64_t serialNo = 0x333231412D4135;
static uint16_t WIDTH = 0;
static uint16_t HEIGHT = 0;
static bool rotate180 = false;
static uint8_t cardRFID[0xC] = {0};
static uint8_t cardDataBuffer[0x20] = {0};
static bool awaitingCardExit = false;
static wchar_t printer_out_path[MAX_PATH];
/* Firmware data */
static uint8_t mainFirmware[0x40] = {0};
static uint8_t dspFirmware[0x40] = {0};
static uint8_t paramFirmware[0x40] = {0};
/* printerInfo variables */
static int32_t PAPERINFO[10];
static int32_t CURVE[3][3];
static uint8_t POLISH[2];
static int32_t MTF[9];
/* C3xxFWDLusb API hooks */
int fwdlusb_open(uint16_t *rResult);
void fwdlusb_close();
int fwdlusb_listupPrinter(uint8_t *rIdArray);
int fwdlusb_listupPrinterSN(uint64_t *rSerialArray);
int fwdlusb_selectPrinter(uint8_t printerId, uint16_t *rResult);
int fwdlusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult);
int fwdlusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen);
int fwdlusb_status(uint16_t *rResult);
int fwdlusb_statusAll(uint8_t *idArray, uint16_t *rResultArray);
int fwdlusb_resetPrinter(uint16_t *rResult);
int fwdlusb_updateFirmware(uint8_t update, LPCSTR filename, uint16_t *rResult);
int fwdlusb_getFirmwareInfo(uint8_t update, LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult);
int fwdlusb_MakeThread(uint16_t maxCount);
int fwdlusb_ReleaseThread(uint16_t *rResult);
int fwdlusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount);
int fwdlusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult);
/* C3xxusb API hooks */
int chcusb_MakeThread(uint16_t maxCount);
int chcusb_open(uint16_t *rResult);
void chcusb_close();
int chcusb_ReleaseThread(uint16_t *rResult);
int chcusb_listupPrinter(uint8_t *rIdArray);
int chcusb_listupPrinterSN(uint64_t *rSerialArray);
int chcusb_selectPrinter(uint8_t printerId, uint16_t *rResult);
int chcusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult);
int chcusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen);
int chcusb_imageformat(
uint16_t format,
uint16_t ncomp,
uint16_t depth,
uint16_t width,
uint16_t height,
uint16_t *rResult);
int chcusb_setmtf(int32_t *mtf);
int chcusb_makeGamma(uint16_t k, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB);
int chcusb_setIcctable(
LPCSTR icc1,
LPCSTR icc2,
uint16_t intents,
uint8_t *intoneR,
uint8_t *intoneG,
uint8_t *intoneB,
uint8_t *outtoneR,
uint8_t *outtoneG,
uint8_t *outtoneB,
uint16_t *rResult);
int chcusb_copies(uint16_t copies, uint16_t *rResult);
int chcusb_status(uint16_t *rResult);
int chcusb_statusAll(uint8_t *idArray, uint16_t *rResultArray);
int chcusb_startpage(uint16_t postCardState, uint16_t *pageId, uint16_t *rResult);
int chcusb_endpage(uint16_t *rResult);
int chcusb_write(uint8_t *data, uint32_t *writeSize, uint16_t *rResult);
int chcusb_writeLaminate(uint8_t *data, uint32_t *writeSize, uint16_t *rResult);
int chcusb_writeHolo(uint8_t *data, uint32_t *writeSize, uint16_t *rResult);
int chcusb_setPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult);
int chcusb_getGamma(LPCSTR filename, uint8_t *r, uint8_t *g, uint8_t *b, uint16_t *rResult);
int chcusb_getMtf(LPCSTR filename, int32_t *mtf, uint16_t *rResult);
int chcusb_cancelCopies(uint16_t pageId, uint16_t *rResult);
int chcusb_setPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult);
int chcusb_getPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult);
int chcusb_blinkLED(uint16_t *rResult);
int chcusb_resetPrinter(uint16_t *rResult);
int chcusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount);
int chcusb_getPrintIDStatus(uint16_t pageId, uint8_t *rBuffer, uint16_t *rResult);
int chcusb_setPrintStandby(uint16_t position, uint16_t *rResult);
int chcusb_testCardFeed(uint16_t mode, uint16_t times, uint16_t *rResult);
int chcusb_exitCard(uint16_t *rResult);
int chcusb_getCardRfidTID(uint8_t *rCardTID, uint16_t *rResult);
int chcusb_commCardRfidReader(uint8_t *sendData, uint8_t *rRecvData, uint32_t sendSize, uint32_t *rRecvSize, uint16_t *rResult);
int chcusb_updateCardRfidReader(uint8_t *data, uint32_t size, uint16_t *rResult);
int chcusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult);
int chcusb_getErrorStatus(uint16_t *rBuffer);
int chcusb_setCutList(uint8_t *rData, uint16_t *rResult);
int chcusb_setLaminatePattern(uint16_t index, uint8_t *rData, uint16_t *rResult);
int chcusb_color_adjustment(LPCSTR filename, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult);
int chcusb_color_adjustmentEx(int32_t a1, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult);
int chcusb_getEEPROM(uint8_t index, uint8_t *rData, uint16_t *rResult);
int chcusb_setParameter(uint8_t a1, uint32_t a2, uint16_t *rResult);
int chcusb_getParameter(uint8_t a1, uint8_t *a2, uint16_t *rResult);
int chcusb_universal_command(int32_t a1, uint8_t a2, int32_t a3, uint8_t *a4, uint16_t *rResult);
/* Bitmap writing utils */
DWORD WriteDataToBitmapFile(
LPCWSTR lpFilePath, DWORD dwBitCount,
DWORD dwWidth, DWORD dwHeight,
PBYTE pbInput, DWORD cbInput,
PBYTE pbMetadata, DWORD cbMetadata,
bool pFlip);
DWORD WriteArrayToFile(LPCSTR lpOutputFilePath, LPVOID lpDataTemp, DWORD nDataSize, BOOL isAppend);
#define MAX_CARDS 36
// big thanks to Coburn and Mitsuhide for helping me figure out this thing
// request format:
// 0xe0 - sync
// 0x?? - command
// 0x?? - payload length
// ... - payload
// 0x?? - checksum (sum of everything except the sync byte)
//
// response format:
// 0xe0 - sync
// 0x?? - command
// 0x?? - status code
// 0x?? - payload length
// ... - payload
// 0x?? - checksum
enum {
DECK_CMD_RESET = 0x41,
DECK_CMD_GET_BOOT_FW_VERSION = 0x84,
DECK_CMD_GET_BOARD_INFO = 0x85,
DECK_CMD_INIT_UNK1 = 0x81,
DECK_CMD_GET_APP_FW_VERSION = 0x42,
DECK_CMD_READ_DATA = 0x02,
DECK_CMD_WRITE = 0x03,
DECK_CMD_INIT_UNK2 = 0x04,
DECK_CMD_INIT_UNK3 = 0x05,
DECK_CMD_READ = 0x06
};
enum {
DECK_READ_START = 0x81,
DECK_READ_DATA = 0x82,
DECK_READ_END = 0x83
};
struct deck_hdr {
uint8_t sync;
uint8_t cmd;
uint8_t nbytes;
};
struct deck_resp_hdr {
uint8_t sync;
uint8_t cmd;
uint8_t status;
uint8_t nbytes;
};
struct deck_resp_get_boot_fw_version {
struct deck_resp_hdr hdr;
uint8_t boot_fw_version;
};
struct deck_resp_get_app_fw_version {
struct deck_resp_hdr hdr;
uint8_t app_fw_version;
};
struct deck_resp_get_board_info {
struct deck_resp_hdr hdr;
uint8_t board[9];
};
struct deck_resp_read_data {
struct deck_resp_hdr hdr;
uint8_t card_data[32];
};
struct deck_resp_read {
struct deck_resp_hdr hdr;
uint8_t card_data[44];
};
union deck_req_any {
struct deck_hdr hdr;
uint8_t bytes[520];
};
static HRESULT deck_handle_irp(struct irp *irp);
static HRESULT deck_handle_irp_locked(struct irp *irp);
static HRESULT deck_req_dispatch(const union deck_req_any *req);
static HRESULT deck_req_get_boot_fw_version(void);
static HRESULT deck_req_get_app_fw_version(void);
static HRESULT deck_req_get_board_info(void);
static HRESULT deck_req_read(void);
static HRESULT deck_req_read_data(void);
static HRESULT deck_req_write(const uint8_t *req_bytes);
static HRESULT deck_req_nop(uint8_t cmd);
static void deck_read_one(void);
static HRESULT deck_frame_accept(const struct iobuf *dest);
static void deck_frame_sync(struct iobuf *src);
static HRESULT deck_frame_decode(struct iobuf *dest, struct iobuf *src);
static HRESULT deck_frame_encode(struct iobuf *dest, const void *ptr, size_t nbytes);
static HRESULT deck_frame_encode_byte(struct iobuf *dest, uint8_t byte);
static CRITICAL_SECTION deck_lock;
static struct uart deck_uart;
static uint8_t deck_written_bytes[1024];
static uint8_t deck_readable_bytes[1024];
static uint8_t current_card_idx = 0;
static bool read_pending = false;
/* C3xxFWDLusb hook tbl. */
static const struct hook_symbol C3XXFWDLusb_hooks[] = {
{.name = "fwdlusb_open",
.patch = fwdlusb_open,
.link = NULL},
{.name = "fwdlusb_close",
.patch = fwdlusb_close,
.link = NULL},
{.name = "fwdlusb_listupPrinter",
.patch = fwdlusb_listupPrinter,
.link = NULL},
{.name = "fwdlusb_listupPrinterSN",
.patch = fwdlusb_listupPrinterSN,
.link = NULL},
{.name = "fwdlusb_selectPrinter",
.patch = fwdlusb_selectPrinter,
.link = NULL},
{.name = "fwdlusb_selectPrinterSN",
.patch = fwdlusb_selectPrinterSN,
.link = NULL},
{.name = "fwdlusb_getPrinterInfo",
.patch = fwdlusb_getPrinterInfo,
.link = NULL},
{.name = "fwdlusb_status",
.patch = fwdlusb_status,
.link = NULL},
{.name = "fwdlusb_statusAll",
.patch = fwdlusb_statusAll,
.link = NULL},
{.name = "fwdlusb_resetPrinter",
.patch = fwdlusb_resetPrinter,
.link = NULL},
{.name = "fwdlusb_updateFirmware",
.patch = fwdlusb_updateFirmware,
.link = NULL},
{.name = "fwdlusb_getFirmwareInfo",
.patch = fwdlusb_getFirmwareInfo,
.link = NULL},
{.name = "fwdlusb_MakeThread",
.patch = fwdlusb_MakeThread,
.link = NULL},
{.name = "fwdlusb_ReleaseThread",
.patch = fwdlusb_ReleaseThread,
.link = NULL},
{.name = "fwdlusb_AttachThreadCount",
.patch = fwdlusb_AttachThreadCount,
.link = NULL},
{.name = "fwdlusb_getErrorLog",
.patch = fwdlusb_getErrorLog,
.link = NULL},
};
/* C310A-Busb/C320Ausb/C330Ausb hook tbl. */
static const struct hook_symbol C3XXusb_hooks[] = {
{.name = "chcusb_MakeThread",
.patch = chcusb_MakeThread,
.link = NULL},
{.name = "chcusb_open",
.patch = chcusb_open,
.link = NULL},
{.name = "chcusb_close",
.patch = chcusb_close,
.link = NULL},
{.name = "chcusb_ReleaseThread",
.patch = chcusb_ReleaseThread,
.link = NULL},
{.name = "chcusb_listupPrinter",
.patch = chcusb_listupPrinter,
.link = NULL},
{.name = "chcusb_listupPrinterSN",
.patch = chcusb_listupPrinterSN,
.link = NULL},
{.name = "chcusb_selectPrinter",
.patch = chcusb_selectPrinter,
.link = NULL},
{.name = "chcusb_selectPrinterSN",
.patch = chcusb_selectPrinterSN,
.link = NULL},
{.name = "chcusb_getPrinterInfo",
.patch = chcusb_getPrinterInfo,
.link = NULL},
{.name = "chcusb_imageformat",
.patch = chcusb_imageformat,
.link = NULL},
{.name = "chcusb_setmtf",
.patch = chcusb_setmtf,
.link = NULL},
{.name = "chcusb_makeGamma",
.patch = chcusb_makeGamma,
.link = NULL},
{.name = "chcusb_setIcctable",
.patch = chcusb_setIcctable,
.link = NULL},
{.name = "chcusb_copies",
.patch = chcusb_copies,
.link = NULL},
{.name = "chcusb_status",
.patch = chcusb_status,
.link = NULL},
{.name = "chcusb_statusAll",
.patch = chcusb_statusAll,
.link = NULL},
{.name = "chcusb_startpage",
.patch = chcusb_startpage,
.link = NULL},
{.name = "chcusb_endpage",
.patch = chcusb_endpage,
.link = NULL},
{.name = "chcusb_write",
.patch = chcusb_write,
.link = NULL},
{.name = "chcusb_writeLaminate",
.patch = chcusb_writeLaminate,
.link = NULL},
{.name = "chcusb_writeHolo",
.patch = chcusb_writeHolo,
.link = NULL},
{.name = "chcusb_setPrinterInfo",
.patch = chcusb_setPrinterInfo,
.link = NULL},
{.name = "chcusb_getGamma",
.patch = chcusb_getGamma,
.link = NULL},
{.name = "chcusb_getMtf",
.patch = chcusb_getMtf,
.link = NULL},
{.name = "chcusb_cancelCopies",
.patch = chcusb_cancelCopies,
.link = NULL},
{.name = "chcusb_setPrinterToneCurve",
.patch = chcusb_setPrinterToneCurve,
.link = NULL},
{.name = "chcusb_getPrinterToneCurve",
.patch = chcusb_getPrinterToneCurve,
.link = NULL},
{.name = "chcusb_blinkLED",
.patch = chcusb_blinkLED,
.link = NULL},
{.name = "chcusb_resetPrinter",
.patch = chcusb_resetPrinter,
.link = NULL},
{.name = "chcusb_AttachThreadCount",
.patch = chcusb_AttachThreadCount,
.link = NULL},
{.name = "chcusb_getPrintIDStatus",
.patch = chcusb_getPrintIDStatus,
.link = NULL},
{.name = "chcusb_setPrintStandby",
.patch = chcusb_setPrintStandby,
.link = NULL},
{.name = "chcusb_testCardFeed",
.patch = chcusb_testCardFeed,
.link = NULL},
{.name = "chcusb_exitCard",
.patch = chcusb_exitCard,
.link = NULL},
{.name = "chcusb_getCardRfidTID",
.patch = chcusb_getCardRfidTID,
.link = NULL},
{.name = "chcusb_commCardRfidReader",
.patch = chcusb_commCardRfidReader,
.link = NULL},
{.name = "chcusb_updateCardRfidReader",
.patch = chcusb_updateCardRfidReader,
.link = NULL},
{.name = "chcusb_getErrorLog",
.patch = chcusb_getErrorLog,
.link = NULL},
{.name = "chcusb_getErrorStatus",
.patch = chcusb_getErrorStatus,
.link = NULL},
{.name = "chcusb_setCutList",
.patch = chcusb_setCutList,
.link = NULL},
{.name = "chcusb_setLaminatePattern",
.patch = chcusb_setLaminatePattern,
.link = NULL},
{.name = "chcusb_color_adjustment",
.patch = chcusb_color_adjustment,
.link = NULL},
{.name = "chcusb_color_adjustmentEx",
.patch = chcusb_color_adjustmentEx,
.link = NULL},
{.name = "chcusb_getEEPROM",
.patch = chcusb_getEEPROM,
.link = NULL},
{.name = "chcusb_setParameter",
.patch = chcusb_setParameter,
.link = NULL},
{.name = "chcusb_getParameter",
.patch = chcusb_getParameter,
.link = NULL},
{.name = "chcusb_universal_command",
.patch = chcusb_universal_command,
.link = NULL},
};
/* C300usb hook tbl */
static struct hook_symbol C300usb_hooks[] = {
{.name = "chcusb_MakeThread",
.patch = chcusb_MakeThread,
.link = NULL},
{.name = "chcusb_open",
.patch = chcusb_open,
.link = NULL},
{.name = "chcusb_close",
.patch = chcusb_close,
.link = NULL},
{.name = "chcusb_ReleaseThread",
.patch = chcusb_ReleaseThread,
.link = NULL},
{.name = "chcusb_listupPrinter",
.patch = chcusb_listupPrinter,
.link = NULL},
{.name = "chcusb_listupPrinterSN",
.patch = chcusb_listupPrinterSN,
.link = NULL},
{.name = "chcusb_selectPrinter",
.patch = chcusb_selectPrinter,
.link = NULL},
{.name = "chcusb_selectPrinterSN",
.patch = chcusb_selectPrinterSN,
.link = NULL},
{.name = "chcusb_getPrinterInfo",
.patch = chcusb_getPrinterInfo,
.link = NULL},
{.name = "chcusb_imageformat",
.patch = chcusb_imageformat,
.link = NULL},
{.name = "chcusb_setmtf",
.patch = chcusb_setmtf,
.link = NULL},
{.name = "chcusb_makeGamma",
.patch = chcusb_makeGamma,
.link = NULL},
{.name = "chcusb_setIcctable",
.patch = chcusb_setIcctable,
.link = NULL},
{.name = "chcusb_copies",
.patch = chcusb_copies,
.link = NULL},
{.name = "chcusb_status",
.patch = chcusb_status,
.link = NULL},
{.name = "chcusb_statusAll",
.patch = chcusb_statusAll,
.link = NULL},
{.name = "chcusb_startpage",
.patch = chcusb_startpage,
.link = NULL},
{.name = "chcusb_endpage",
.patch = chcusb_endpage,
.link = NULL},
{.name = "chcusb_write",
.patch = chcusb_write,
.link = NULL},
{.name = "chcusb_writeLaminate",
.patch = chcusb_writeLaminate,
.link = NULL},
{.name = "chcusb_setPrinterInfo",
.patch = chcusb_setPrinterInfo,
.link = NULL},
{.name = "chcusb_getGamma",
.patch = chcusb_getGamma,
.link = NULL},
{.name = "chcusb_getMtf",
.patch = chcusb_getMtf,
.link = NULL},
{.name = "chcusb_cancelCopies",
.patch = chcusb_cancelCopies,
.link = NULL},
{.name = "chcusb_setPrinterToneCurve",
.patch = chcusb_setPrinterToneCurve,
.link = NULL},
{.name = "chcusb_getPrinterToneCurve",
.patch = chcusb_getPrinterToneCurve,
.link = NULL},
{.name = "chcusb_blinkLED",
.patch = chcusb_blinkLED,
.link = NULL},
{.name = "chcusb_resetPrinter",
.patch = chcusb_resetPrinter,
.link = NULL},
{.name = "chcusb_AttachThreadCount",
.patch = chcusb_AttachThreadCount,
.link = NULL},
{.name = "chcusb_getPrintIDStatus",
.patch = chcusb_getPrintIDStatus,
.link = NULL},
{.name = "chcusb_setPrintStandby",
.patch = chcusb_setPrintStandby,
.link = NULL},
{.name = "chcusb_testCardFeed",
.patch = chcusb_testCardFeed,
.link = NULL},
{.name = "chcusb_setParameter",
.patch = chcusb_setParameter,
.link = NULL},
{.name = "chcusb_getParameter",
.patch = chcusb_getParameter,
.link = NULL},
{.name = "chcusb_getErrorStatus",
.patch = chcusb_getErrorStatus,
.link = NULL},
{.name = "chcusb_setCutList",
.patch = chcusb_setCutList,
.link = NULL},
{.name = "chcusb_setLaminatePattern",
.patch = chcusb_setLaminatePattern,
.link = NULL},
{.name = "chcusb_color_adjustment",
.patch = chcusb_color_adjustment,
.link = NULL},
{.name = "chcusb_color_adjustmentEx",
.patch = chcusb_color_adjustmentEx,
.link = NULL},
{.name = "chcusb_getEEPROM",
.patch = chcusb_getEEPROM,
.link = NULL},
{.name = "chcusb_universal_command",
.patch = chcusb_universal_command,
.link = NULL},
};
static struct printer_config printer_config;
void printer_hook_init(const struct printer_config *cfg, int rfid_port_no, HINSTANCE self) {
HANDLE fwFile = NULL;
DWORD bytesRead = 0;
assert(cfg != NULL);
if (!cfg->enable) {
return;
}
/* Set serial and rotate cfg */
memcpy(&serialNo, cfg->serial_no, sizeof(serialNo));
_byteswap_uint64(serialNo);
rotate180 = cfg->rotate_180;
memcpy(&printer_config, cfg, sizeof(*cfg));
hook_table_apply(NULL, "C300usb.dll", C300usb_hooks, _countof(C300usb_hooks));
hook_table_apply(NULL, "C300FWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks));
hook_table_apply(NULL, "C310Ausb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks));
hook_table_apply(NULL, "C310Busb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks));
hook_table_apply(NULL, "C310FWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks));
hook_table_apply(NULL, "C310BFWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks));
hook_table_apply(NULL, "C320Ausb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks));
hook_table_apply(NULL, "C320AFWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks));
hook_table_apply(NULL, "C330Ausb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks));
hook_table_apply(NULL, "C330AFWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks));
if (self != NULL) {
dll_hook_push(self, L"C300usb.dll"); // TODO: This doesn't work. Unity moment
dll_hook_push(self, L"C300FWDLusb.dll"); // TODO: ...and this...
dll_hook_push(self, L"C310Ausb.dll");
dll_hook_push(self, L"C310Busb.dll"); // TODO: ...and this...
dll_hook_push(self, L"C310FWDLusb.dll");
dll_hook_push(self, L"C310BFWDLusb.dll"); // TODO: ...aaaand this.
dll_hook_push(self, L"C320Ausb.dll");
dll_hook_push(self, L"C320AFWDLusb.dll");
dll_hook_push(self, L"C330Ausb.dll");
dll_hook_push(self, L"C330AFWDLusb.dll");
}
// Load firmware if has previously been written to
fwFile = CreateFileW(cfg->main_fw_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fwFile != NULL) {
ReadFile(fwFile, mainFirmware, sizeof(mainFirmware), &bytesRead, NULL);
CloseHandle(fwFile);
}
fwFile = CreateFileW(cfg->dsp_fw_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fwFile != NULL) {
ReadFile(fwFile, dspFirmware, sizeof(dspFirmware), &bytesRead, NULL);
CloseHandle(fwFile);
}
fwFile = CreateFileW(cfg->param_fw_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fwFile != NULL) {
ReadFile(fwFile, paramFirmware, sizeof(dspFirmware), &bytesRead, NULL);
CloseHandle(fwFile);
}
CreateDirectoryW(cfg->printer_out_path, NULL);
memcpy(printer_out_path, cfg->printer_out_path, MAX_PATH);
if (rfid_port_no != 0) {
InitializeCriticalSection(&deck_lock);
uart_init(&deck_uart, rfid_port_no);
deck_uart.written.bytes = deck_written_bytes;
deck_uart.written.nbytes = sizeof(deck_written_bytes);
deck_uart.readable.bytes = deck_readable_bytes;
deck_uart.readable.nbytes = sizeof(deck_readable_bytes);
dprintf("Printer: RFID: hook enabled.\n");
if (FAILED(iohook_push_handler(deck_handle_irp))) {
dprintf("Printer: RFID: failed to hook IRP handler.\n");
}
}
dprintf("Printer: hook enabled.\n");
}
static void generate_rfid(void) {
for (int i = 0; i < sizeof(cardRFID); i++)
cardRFID[i] = rand();
dprintf("Printer: New card RFID:\n");
dump(cardRFID, sizeof(cardRFID));
}
static HRESULT deck_handle_irp(struct irp *irp) {
HRESULT hr;
assert(irp != NULL);
if (!uart_match_irp(&deck_uart, irp)) {
return iohook_invoke_next(irp);
}
EnterCriticalSection(&deck_lock);
hr = deck_handle_irp_locked(irp);
LeaveCriticalSection(&deck_lock);
return hr;
}
static HRESULT deck_handle_irp_locked(struct irp *irp) {
uint8_t req[1024];
struct iobuf req_iobuf;
HRESULT hr;
if (irp->op == IRP_OP_OPEN) {
dprintf("Printer: RFID: Starting backend\n");
}
hr = uart_handle_irp(&deck_uart, irp);
if (SUCCEEDED(hr) && irp->op == IRP_OP_READ && read_pending == true) {
deck_read_one();
return S_OK;
}
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
for (;;) {
// if (deck_uart.written.pos != 0) {
// dprintf("Printer: RFID: TX Buffer:\n");
// dump_iobuf(&deck_uart.written);
// }
req_iobuf.bytes = req;
req_iobuf.nbytes = sizeof(req);
req_iobuf.pos = 0;
hr = deck_frame_decode(&req_iobuf, &deck_uart.written);
if (hr != S_OK) {
if (FAILED(hr)) {
dprintf("Printer: RFID: Deframe error: %x, %d %d\n", (int)hr, (int)req_iobuf.nbytes, (int)req_iobuf.pos);
}
return hr;
}
// dprintf("Printer: RFID: Deframe Buffer:\n");
// dump_iobuf(&req_iobuf);
hr = deck_req_dispatch((const union deck_req_any *)&req);
if (FAILED(hr)) {
dprintf("Printer: RFID: Processing error: %x\n", (int)hr);
}
// dprintf("Printer: RFID: Written bytes:\n");
// dump_iobuf(&deck_uart.readable);
}
}
static HRESULT deck_req_dispatch(const union deck_req_any *req) {
switch (req->hdr.cmd) {
case DECK_CMD_RESET:
case DECK_CMD_INIT_UNK1:
case DECK_CMD_INIT_UNK2:
case DECK_CMD_INIT_UNK3:
return deck_req_nop(req->hdr.cmd);
case DECK_CMD_GET_BOOT_FW_VERSION:
return deck_req_get_boot_fw_version();
case DECK_CMD_GET_APP_FW_VERSION:
return deck_req_get_app_fw_version();
case DECK_CMD_GET_BOARD_INFO:
return deck_req_get_board_info();
case DECK_CMD_READ:
return deck_req_read();
case DECK_CMD_READ_DATA:
return deck_req_read_data();
case DECK_CMD_WRITE:
return deck_req_write(req->bytes);
default:
dprintf("Printer: RFID: Unhandled command %#02x\n", req->hdr.cmd);
return S_OK;
}
}
static HRESULT deck_req_get_boot_fw_version(void) {
struct deck_resp_get_boot_fw_version resp;
dprintf("Printer: RFID: Get Boot FW Version\n");
resp.hdr.sync = 0xE0;
resp.hdr.cmd = DECK_CMD_GET_BOOT_FW_VERSION;
resp.hdr.status = 0;
resp.hdr.nbytes = 1;
resp.boot_fw_version = 0x90;
return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
}
static HRESULT deck_req_get_app_fw_version(void) {
struct deck_resp_get_app_fw_version resp;
dprintf("Printer: RFID: Get App FW Version\n");
resp.hdr.sync = 0xE0;
resp.hdr.cmd = DECK_CMD_GET_APP_FW_VERSION;
resp.hdr.status = 0;
resp.hdr.nbytes = 1;
resp.app_fw_version = 0x90;
return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
}
static HRESULT deck_req_get_board_info(void) {
struct deck_resp_get_board_info resp;
dprintf("Printer: RFID: Get Board Info\n");
resp.hdr.sync = 0xE0;
resp.hdr.cmd = DECK_CMD_GET_BOARD_INFO;
resp.hdr.status = 0;
resp.hdr.nbytes = 9;
memcpy(resp.board, (void *)"837-15347", 9);
return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
}
static HRESULT deck_req_read(void) {
struct deck_resp_read resp;
dprintf("Printer: RFID: Read Card\n");
resp.hdr.sync = 0xE0;
resp.hdr.cmd = DECK_CMD_READ;
resp.hdr.status = DECK_READ_START;
resp.hdr.nbytes = 0;
current_card_idx = 0;
read_pending = true;
return deck_frame_encode(&deck_uart.readable, &resp.hdr, sizeof(resp.hdr));
}
static HRESULT deck_req_read_data(void) {
struct deck_resp_read_data resp;
dprintf("Printer: RFID: Read Card Data\n");
resp.hdr.sync = 0xE0;
resp.hdr.cmd = DECK_CMD_READ_DATA;
resp.hdr.status = 0;
resp.hdr.nbytes = 32;
memcpy(resp.card_data, cardDataBuffer, 32);
return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
}
static HRESULT deck_req_write(const uint8_t *req_bytes) {
struct deck_resp_hdr resp;
uint8_t off;
resp.sync = 0xE0;
resp.cmd = DECK_CMD_WRITE;
resp.status = 0;
resp.nbytes = 0;
off = (req_bytes[5] - 1) * 2;
cardDataBuffer[off] = req_bytes[6];
cardDataBuffer[off + 1] = req_bytes[7];
if (req_bytes[5] == 0x10) {
dprintf("Printer: RFID: Card Data Buffer: \n");
dump(cardDataBuffer, 0x20);
}
return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
}
static void deck_read_one(void) {
struct deck_resp_read resp;
dprintf("Printer: RFID: Read One Card\n");
resp.hdr.sync = 0xE0;
resp.hdr.cmd = DECK_CMD_READ;
if (current_card_idx < 1) {
resp.hdr.status = DECK_READ_DATA;
resp.hdr.nbytes = 44;
memset(resp.card_data, 0, 44);
memcpy(resp.card_data, cardRFID, 0xC);
memcpy(resp.card_data + 0x0C, cardDataBuffer, 0x20);
dump(resp.card_data, 44);
deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
current_card_idx++;
} else {
resp.hdr.status = DECK_READ_END;
resp.hdr.nbytes = 0;
deck_frame_encode(&deck_uart.readable, &resp.hdr, sizeof(resp.hdr));
read_pending = false;
}
}
static HRESULT deck_req_nop(uint8_t cmd) {
struct deck_resp_hdr resp;
dprintf("Printer: RFID: No-op cmd %#02x\n", cmd);
resp.sync = 0xE0;
resp.cmd = cmd;
resp.status = 0;
resp.nbytes = 0;
return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp));
}
static void deck_frame_sync(struct iobuf *src) {
size_t i;
for (i = 0; i < src->pos && src->bytes[i] != 0xE0; i++)
;
src->pos -= i;
memmove(&src->bytes[0], &src->bytes[i], i);
}
static HRESULT deck_frame_accept(const struct iobuf *dest) {
if (dest->pos < 2 || dest->pos != dest->bytes[2] + 4) {
return S_FALSE;
}
return S_OK;
}
static HRESULT deck_frame_decode(struct iobuf *dest, struct iobuf *src) {
uint8_t byte;
bool escape;
size_t i;
HRESULT hr;
assert(dest != NULL);
assert(dest->bytes != NULL || dest->nbytes == 0);
assert(dest->pos <= dest->nbytes);
assert(src != NULL);
assert(src->bytes != NULL || src->nbytes == 0);
assert(src->pos <= src->nbytes);
dest->pos = 0;
escape = false;
for (i = 0, hr = S_FALSE; i < src->pos && hr == S_FALSE; i++) {
/* Step the FSM to unstuff another byte */
byte = src->bytes[i];
if (dest->pos >= dest->nbytes) {
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
} else if (i == 0) {
dest->bytes[dest->pos++] = byte;
} else if (byte == 0xE0) {
hr = E_FAIL;
} else if (byte == 0xD0) {
if (escape) {
hr = E_FAIL;
}
escape = true;
} else if (escape) {
dest->bytes[dest->pos++] = byte + 1;
escape = false;
} else {
dest->bytes[dest->pos++] = byte;
}
/* Try to accept the packet we've built up so far */
if (SUCCEEDED(hr)) {
hr = deck_frame_accept(dest);
}
}
/* Handle FSM terminal state */
if (hr != S_FALSE) {
/* Frame was either accepted or rejected, remove it from src */
memmove(&src->bytes[0], &src->bytes[i], src->pos - i);
src->pos -= i;
}
return hr;
}
static HRESULT deck_frame_encode(
struct iobuf *dest,
const void *ptr,
size_t nbytes) {
const uint8_t *src;
uint8_t checksum;
uint8_t byte;
size_t i;
HRESULT hr;
assert(dest != NULL);
assert(dest->bytes != NULL || dest->nbytes == 0);
assert(dest->pos <= dest->nbytes);
assert(ptr != NULL);
src = ptr;
assert(nbytes >= 2 && src[0] == 0xE0 && src[3] + 4 == nbytes);
if (dest->pos >= dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
dest->bytes[dest->pos++] = 0xE0;
checksum = 0x0;
for (i = 1; i < nbytes; i++) {
byte = src[i];
checksum += byte;
hr = deck_frame_encode_byte(dest, byte);
if (FAILED(hr)) {
return hr;
}
}
return deck_frame_encode_byte(dest, checksum);
}
static HRESULT deck_frame_encode_byte(struct iobuf *dest, uint8_t byte) {
if (byte == 0xD0 || byte == 0xE0) {
if (dest->pos + 2 > dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
dest->bytes[dest->pos++] = 0xD0;
dest->bytes[dest->pos++] = byte - 1;
} else {
if (dest->pos + 1 > dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
dest->bytes[dest->pos++] = byte;
}
return S_OK;
}
// C3XXFWDLusb stubs
int fwdlusb_open(uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
void fwdlusb_close() {}
int fwdlusb_listupPrinter(uint8_t *rIdArray) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
memset(rIdArray, 0xFF, 0x80);
rIdArray[0] = idNumber;
return 1;
}
int fwdlusb_listupPrinterSN(uint64_t *rSerialArray) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
memset(rSerialArray, 0xFF, 0x400);
rSerialArray[0] = serialNo;
return 1;
}
int fwdlusb_selectPrinter(uint8_t printerId, uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int fwdlusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int fwdlusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
switch (tagNumber) {
case 0: // getPaperInfo
if (*rLen != 0x67) *rLen = 0x67;
if (rBuffer) memset(rBuffer, 0, *rLen);
return 1;
case 3: // getFirmwareVersion
if (*rLen != 0x99) *rLen = 0x99;
if (rBuffer) {
memset(rBuffer, 0, *rLen);
// bootFirmware
int i = 1;
memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware));
// mainFirmware
i += 0x26;
memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware));
// printParameterTable
i += 0x26;
memcpy(rBuffer + i, paramFirmware, sizeof(paramFirmware));
// dspFirmware (C300 only)
i += 0x26;
memcpy(rBuffer + i, dspFirmware, 0x26);
}
return 1;
case 4: // getPrintCountInfo (C300 only)
if (!rBuffer) {
*rLen = 0x1C;
return 1;
}
int32_t bInfoC300[10] = {0};
uint16_t printCounterC300;
bInfoC300[0] = 22; // printCounter0
bInfoC300[1] = 23; // printCounter1
bInfoC300[2] = 33; // feedRollerCount
bInfoC300[3] = 55; // cutterCount
bInfoC300[4] = 88; // headCount
bInfoC300[5] = 999; // ribbonRemain
bInfoC300[6] = 0; // dummy
if (*rLen <= 0x1Cu) {
memcpy(rBuffer, bInfoC300, *rLen);
} else {
bInfoC300[7] = 0; // TODO
if (*rLen > 0x20u) *rLen = 0x20;
memcpy(rBuffer, bInfoC300, *rLen);
}
break;
case 5: // getPrintCountInfo
if (!rBuffer) {
*rLen = 0x28;
return 1;
}
int32_t bInfo[10] = {0};
bInfo[0] = 22; // printCounter0
bInfo[1] = 23; // printCounter1
bInfo[2] = 33; // feedRollerCount
bInfo[3] = 55; // cutterCount
bInfo[4] = 88; // headCount
bInfo[5] = 999; // ribbonRemain
bInfo[6] = 99; // holoHeadCount
if (*rLen <= 0x1Cu) {
memcpy(rBuffer, bInfo, *rLen);
} else {
bInfo[7] = 69; // paperCount
bInfo[8] = 21; // printCounter2
bInfo[9] = 20; // holoPrintCounter
if (*rLen > 0x28u) *rLen = 0x28;
memcpy(rBuffer, bInfo, *rLen);
}
break;
case 26: // getPrinterSerial
if (*rLen != 8) *rLen = 8;
if (rBuffer) memcpy(rBuffer, &serialNo, 8);
return 1;
default:
dprintf("Printer: %s: Unknown parameter 'tagNumber' value %d.\n", __func__, tagNumber);
break;
}
return 1;
}
int fwdlusb_status(uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int fwdlusb_statusAll(uint8_t *idArray, uint16_t *rResultArray) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
for (int i = 0; *(uint8_t *)(idArray + i) != 255 && i < 128; ++i) {
*(uint16_t *)(rResultArray + 2 * i) = 0;
}
return 1;
}
int fwdlusb_resetPrinter(uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int fwdlusb_getFirmwareVersion(uint8_t *buffer, int size) {
int8_t a;
uint32_t b = 0;
for (int32_t i = 0; i < size; ++i) {
if (*(int8_t *)(buffer + i) < 0x30 || *(int8_t *)(buffer + i) > 0x39) {
if (*(int8_t *)(buffer + i) < 0x41 || *(int8_t *)(buffer + i) > 0x46) {
if (*(int8_t *)(buffer + i) < 0x61 || *(int8_t *)(buffer + i) > 0x66) {
return 0;
}
a = *(int8_t *)(buffer + i) - 0x57;
} else {
a = *(int8_t *)(buffer + i) - 0x37;
}
} else {
a = *(int8_t *)(buffer + i) - 0x30;
}
b = a + 0x10 * b;
}
return b;
}
int fwdlusb_updateFirmware_main(uint8_t update, LPCSTR filename, uint16_t *rResult) {
DWORD result;
HANDLE fwFile = NULL;
DWORD bytesWritten = 0;
if (filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
{
if (rResult) *rResult = 1005;
result = 0;
}
DWORD read;
uint8_t buffer[0x40];
result = ReadFile(hFile, buffer, 0x40, &read, NULL);
CloseHandle(hFile);
if (result && read > 0x24) {
uint8_t rBuffer[0x40] = {0};
memcpy(rBuffer, buffer + 0x2, 0x8);
memcpy(rBuffer + 0x8, buffer + 0xA, 0x10);
memcpy(rBuffer + 0x18, buffer + 0x20, 0xA);
*(rBuffer + 0x22) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1A, 0x2);
*(rBuffer + 0x23) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1C, 0x2);
memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2);
memcpy(mainFirmware, rBuffer, 0x40);
fwFile = CreateFileW(printer_config.main_fw_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fwFile != NULL) {
WriteFile(fwFile, rBuffer, 0x40, &bytesWritten, NULL);
CloseHandle(fwFile);
}
if (rResult) *rResult = 0;
result = 1;
} else {
if (rResult) *rResult = 1005;
result = 0;
}
} else {
if (rResult) *rResult = 1006;
result = 0;
}
return result;
}
int fwdlusb_updateFirmware_dsp(uint8_t update, LPCSTR filename, uint16_t *rResult) {
DWORD result;
HANDLE fwFile = NULL;
DWORD bytesWritten = 0;
if (filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
{
if (rResult) *rResult = 1005;
result = 0;
}
DWORD read;
uint8_t buffer[0x40];
result = ReadFile(hFile, buffer, 0x40, &read, NULL);
CloseHandle(hFile);
if (result && read > 0x24) {
uint8_t rBuffer[0x40] = {0};
memcpy(rBuffer, buffer + 0x2, 8);
memcpy(rBuffer + 0x8, buffer + 0xA, 0x10);
memcpy(rBuffer + 0x18, buffer + 0x20, 0xA);
memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1);
memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1);
memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2);
memcpy(dspFirmware, rBuffer, 0x40);
fwFile = CreateFileW(printer_config.dsp_fw_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fwFile != NULL) {
WriteFile(fwFile, rBuffer, 0x40, &bytesWritten, NULL);
CloseHandle(fwFile);
}
if (rResult) *rResult = 0;
result = 1;
} else {
if (rResult) *rResult = 1005;
result = 0;
}
} else {
if (rResult) *rResult = 1006;
result = 0;
}
return result;
}
int fwdlusb_updateFirmware_param(uint8_t update, LPCSTR filename, uint16_t *rResult) {
DWORD result;
HANDLE fwFile = NULL;
DWORD bytesWritten = 0;
if (filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
{
if (rResult) *rResult = 1005;
result = 0;
}
DWORD read;
uint8_t buffer[0x40];
result = ReadFile(hFile, buffer, 0x40, &read, NULL);
CloseHandle(hFile);
if (result && read > 0x24) {
uint8_t rBuffer[0x40] = {0};
memcpy(rBuffer, buffer + 0x2, 8);
memcpy(rBuffer + 0x8, buffer + 0xA, 0x10);
memcpy(rBuffer + 0x18, buffer + 0x20, 0xA);
memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1);
memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1);
memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2);
memcpy(paramFirmware, rBuffer, 0x40);
fwFile = CreateFileW(printer_config.param_fw_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fwFile != NULL) {
WriteFile(fwFile, rBuffer, 0x40, &bytesWritten, NULL);
CloseHandle(fwFile);
}
if (rResult) *rResult = 0;
result = 1;
} else {
if (rResult) *rResult = 1005;
result = 0;
}
} else {
if (rResult) *rResult = 1006;
result = 0;
}
return result;
}
int fwdlusb_updateFirmware(uint8_t update, LPCSTR filename, uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
if (update == 1) {
return fwdlusb_updateFirmware_main(update, filename, rResult);
} else if (update == 2) {
return fwdlusb_updateFirmware_dsp(update, filename, rResult);
} else if (update == 3) {
return fwdlusb_updateFirmware_param(update, filename, rResult);
} else {
*rResult = 0;
return 1;
}
}
int fwdlusb_getFirmwareInfo_main(LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) {
DWORD result;
if (filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
{
if (rResult) *rResult = 1005;
result = 0;
}
DWORD read;
uint8_t buffer[0x40];
result = ReadFile(hFile, buffer, 0x40, &read, NULL);
if (result && read > 0x24) {
memcpy(rBuffer, buffer + 0x2, 0x8);
memcpy(rBuffer + 0x8, buffer + 0xA, 0x10);
memcpy(rBuffer + 0x18, buffer + 0x20, 0xA);
*(rBuffer + 0x22) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1A, 0x2);
*(rBuffer + 0x23) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1C, 0x2);
memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2);
if (rResult) *rResult = 0;
result = 1;
} else {
if (rResult) *rResult = 1005;
result = 0;
}
} else {
if (rResult) *rResult = 1006;
result = 0;
}
return result;
}
int fwdlusb_getFirmwareInfo_dsp(LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) {
DWORD result;
if (filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
{
if (rResult) *rResult = 1005;
result = 0;
}
DWORD read;
uint8_t buffer[0x40];
result = ReadFile(hFile, buffer, 0x40, &read, NULL);
if (result && read > 0x24) {
memcpy(rBuffer, buffer + 0x2, 8);
memcpy(rBuffer + 0x8, buffer + 0xA, 0x10);
memcpy(rBuffer + 0x18, buffer + 0x20, 0xA);
memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1);
memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1);
memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2);
if (rResult) *rResult = 0;
result = 1;
} else {
if (rResult) *rResult = 1005;
result = 0;
}
} else {
if (rResult) *rResult = 1006;
result = 0;
}
return result;
}
int fwdlusb_getFirmwareInfo_param(LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) {
DWORD result;
if (filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
{
if (rResult) *rResult = 1005;
result = 0;
}
DWORD read;
uint8_t buffer[0x40];
result = ReadFile(hFile, buffer, 0x40, &read, NULL);
if (result && read > 0x24) {
memcpy(rBuffer, buffer + 0x2, 8);
memcpy(rBuffer + 0x8, buffer + 0xA, 0x10);
memcpy(rBuffer + 0x18, buffer + 0x20, 0xA);
memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1);
memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1);
memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2);
if (rResult) *rResult = 0;
result = 1;
} else {
if (rResult) *rResult = 1005;
result = 0;
}
} else {
if (rResult) *rResult = 1006;
result = 0;
}
return result;
}
int fwdlusb_getFirmwareInfo(uint8_t update, LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s(update: %d, filename: %s)\n", __func__, update, filename);
if (!rBuffer) {
*rLen = 38;
return 1;
}
if (*rLen > 38) *rLen = 38;
if (update == 1) {
return fwdlusb_getFirmwareInfo_main(filename, rBuffer, rLen, rResult);
} else if (update == 2) {
return fwdlusb_getFirmwareInfo_dsp(filename, rBuffer, rLen, rResult);
} else if (update == 3) {
return fwdlusb_getFirmwareInfo_param(filename, rBuffer, rLen, rResult);
} else {
if (rResult) *rResult = 0;
return 1;
}
}
int fwdlusb_MakeThread(uint16_t maxCount) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
return 1;
}
int fwdlusb_ReleaseThread(uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int fwdlusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rCount = 0;
*rMaxCount = 1;
return 1;
}
int fwdlusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult) {
dprintf("Printer: C3XXFWDLusb: %s\n", __func__);
*rResult = 0;
return 1;
}
// C3XXusb stubs
int chcusb_MakeThread(uint16_t maxCount) {
dprintf("Printer: C3XXusb: %s\n", __func__);
return 1;
}
int chcusb_open(uint16_t *rResult) {
// Seed random for card id generation
srand(time(NULL));
generate_rfid();
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
void chcusb_close() {
dprintf("Printer: C3XXusb: %s\n", __func__);
}
int chcusb_ReleaseThread(uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
return 1;
}
int chcusb_listupPrinter(uint8_t *rIdArray) {
dprintf("Printer: C3XXusb: %s\n", __func__);
memset(rIdArray, 0xFF, 0x80);
rIdArray[0] = idNumber;
return 1;
}
int chcusb_listupPrinterSN(uint64_t *rSerialArray) {
dprintf("Printer: C3XXusb: %s\n", __func__);
memset(rSerialArray, 0xFF, 0x400);
rSerialArray[0] = serialNo;
return 1;
}
int chcusb_selectPrinter(uint8_t printerId, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen) {
// dprintf("Printer: C3XXusb: %s\n", __func__);
switch (tagNumber) {
// getPaperInfo
case 0:
if (*rLen != 0x67) *rLen = 0x67;
if (rBuffer) memset(rBuffer, 0, *rLen);
break;
case 3: // getFirmwareVersion
if (*rLen != 0x99) *rLen = 0x99;
if (rBuffer) {
memset(rBuffer, 0, *rLen);
// bootFirmware
int i = 1;
memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware));
// mainFirmware
i += 0x26;
memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware));
// printParameterTable
i += 0x26;
memcpy(rBuffer + i, paramFirmware, sizeof(paramFirmware));
// dspFirmware (C300 only)
i += 0x26;
memcpy(rBuffer + i, dspFirmware, 0x26);
}
break;
case 4: // getPrintCountInfo (C300 only)
if (!rBuffer) {
*rLen = 0x1C;
return 1;
}
int32_t bInfoC300[10] = {0};
bInfoC300[0] = 22; // printCounter0
bInfoC300[1] = 23; // printCounter1
bInfoC300[2] = 33; // feedRollerCount
bInfoC300[3] = 55; // cutterCount
bInfoC300[4] = 88; // headCount
bInfoC300[5] = 999; // ribbonRemain
bInfoC300[6] = 0; // dummy
if (*rLen <= 0x1Cu) {
memcpy(rBuffer, bInfoC300, *rLen);
} else {
bInfoC300[7] = 0; // TODO
if (*rLen > 0x20u) *rLen = 0x20;
memcpy(rBuffer, bInfoC300, *rLen);
}
break;
case 5: // getPrintCountInfo2 (C310A and later)
if (!rBuffer) {
*rLen = 0x28;
return 1;
}
int32_t bInfo[10] = {0};
bInfo[0] = 22; // printCounter0
bInfo[1] = 23; // printCounter1
bInfo[2] = 33; // feedRollerCount
bInfo[3] = 55; // cutterCount
bInfo[4] = 88; // headCount
bInfo[5] = 999; // ribbonRemain
bInfo[6] = 99; // holoHeadCount
if (*rLen <= 0x1Cu) {
memcpy(rBuffer, bInfo, *rLen);
} else {
bInfo[7] = 69; // paperCount
bInfo[8] = 21; // printCounter2
bInfo[9] = 20; // holoPrintCounter
if (*rLen > 0x28u) *rLen = 0x28;
memcpy(rBuffer, bInfo, *rLen);
}
break;
case 6: // pageStatusInfo
*rLen = 32;
if (rBuffer) {
memset(rBuffer, 0, 32);
rBuffer[0] = 88; // holoRemain
rBuffer[1] = 0;
rBuffer[2] = 0;
rBuffer[3] = 0;
}
break;
case 7: // svc
*rLen = 2;
if (rBuffer) {
memset(rBuffer, 0, 2);
rBuffer[0] = 0; // mainError
rBuffer[1] = 0; // subError
}
break;
case 8: // printStandby
*rLen = 1;
if (awaitingCardExit)
*rBuffer = 0xF0;
else
*rBuffer = 0;
break;
case 16: // memoryInfo
*rLen = 18;
if (rBuffer) memset(rBuffer, 0, 18);
break;
case 20: // printMode
dprintf("Printer: C3XXusb: Unimpl tagNumber 20\n");
break;
case 26: // getPrinterSerial
if (*rLen != 8) *rLen = 8;
if (rBuffer) memcpy(rBuffer, &serialNo, 8);
break;
case 30: // TODO
dprintf("Printer: C3XXusb: Unimpl tagNumber 30\n");
break;
case 31: // TODO, possibly CardRFIDCheck?
*rLen = 1;
if (rBuffer) memset(rBuffer, 0, 1);
break;
case 40: // temperature
*rLen = 10;
if (rBuffer) {
memset(rBuffer, 0, 10);
rBuffer[0] = 1;
rBuffer[1] = 2;
rBuffer[2] = 3;
}
break;
case 50: // errHistory
*rLen = 61;
if (rBuffer) memset(rBuffer, 0, 61);
break;
case 60: // getToneTable
*rLen = 6;
if (rBuffer) memset(rBuffer, 0, 6);
break;
default:
dprintf("Printer: unknown tagNumber, %d", tagNumber);
break;
}
return 1;
}
int chcusb_imageformat(
uint16_t format,
uint16_t ncomp,
uint16_t depth,
uint16_t width,
uint16_t height,
uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
WIDTH = width;
HEIGHT = height;
*rResult = 0;
return 1;
}
int chcusb_setmtf(int32_t *mtf) {
dprintf("Printer: C3XXusb: %s\n", __func__);
memcpy(MTF, mtf, sizeof(MTF));
return 1;
}
int chcusb_makeGamma(uint16_t k, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB) {
dprintf("Printer: C3XXusb: %s\n", __func__);
uint8_t tone;
int32_t value;
double power;
double factor = (double)k / 100.0;
for (int i = 0; i < 256; ++i) {
power = pow((double)i, factor);
value = (int)(power / pow(255.0, factor) * 255.0);
if (value > 255)
tone = 255;
if (value >= 0)
tone = value;
else
tone = 0;
if (intoneR)
*(uint8_t *)(intoneR + i) = tone;
if (intoneG)
*(uint8_t *)(intoneG + i) = tone;
if (intoneB)
*(uint8_t *)(intoneB + i) = tone;
}
return 1;
}
int chcusb_setIcctable(
LPCSTR icc1,
LPCSTR icc2,
uint16_t intents,
uint8_t *intoneR,
uint8_t *intoneG,
uint8_t *intoneB,
uint8_t *outtoneR,
uint8_t *outtoneG,
uint8_t *outtoneB,
uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
for (int i = 0; i < 256; ++i) {
intoneR[i] = i;
intoneG[i] = i;
intoneB[i] = i;
outtoneR[i] = i;
outtoneG[i] = i;
outtoneB[i] = i;
}
*rResult = 0;
return 1;
}
int chcusb_copies(uint16_t copies, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_status(uint16_t *rResult) {
// dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_statusAll(uint8_t *idArray, uint16_t *rResultArray) {
dprintf("Printer: C3XXusb: %s\n", __func__);
for (int i = 0; *(uint8_t *)(idArray + i) != 255 && i < 128; ++i) {
*(uint16_t *)(rResultArray + 2 * i) = 0;
}
return 1;
}
int chcusb_startpage(uint16_t postCardState, uint16_t *pageId, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*pageId = 1;
*rResult = 0;
return 1;
}
int chcusb_endpage(uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
awaitingCardExit = true;
*rResult = 0;
return 1;
}
int chcusb_write(uint8_t *data, uint32_t *writeSize, uint16_t *rResult) {
SYSTEMTIME t;
GetLocalTime(&t);
wchar_t dumpPath[MAX_PATH];
uint8_t metadata[44];
swprintf_s(
dumpPath, MAX_PATH,
L"%s\\C3XX_%04d%02d%02d_%02d%02d%02d.bmp",
printer_out_path, t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
memcpy(metadata, cardRFID, 12);
memcpy(metadata + 12, cardDataBuffer, 32);
WriteDataToBitmapFile(dumpPath, 24, WIDTH, HEIGHT, data, *writeSize, metadata, 44, rotate180);
// WriteArrayToFile(dumpPath, data, IMAGE_SIZE, FALSE);
dprintf("Printer: C3XXusb: %s\n", __func__);
dwprintf(L"Printer: File written: %s\n", dumpPath);
*rResult = 0;
return 1;
}
int chcusb_writeLaminate(uint8_t *data, uint32_t *writeSize, uint16_t *rResult) {
SYSTEMTIME t;
GetLocalTime(&t);
char dumpPath[0x80];
sprintf_s(
dumpPath, 0x80,
"C3XXusb_%04d%02d%02d_%02d%02d%02d_writeLaminate.bin",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
// WriteArrayToFile(dumpPath, data, *writeSize, FALSE);
dprintf("Printer: C3XXusb: %s\n", __func__);
// *writeSize = written;
*rResult = 0;
return 1;
}
int chcusb_writeHolo(uint8_t *data, uint32_t *writeSize, uint16_t *rResult) {
SYSTEMTIME t;
GetLocalTime(&t);
char dumpPath[0x80];
sprintf_s(
dumpPath, 0x80,
"C3XXusb_%04d%02d%02d_%02d%02d%02d_writeHolo.bin",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
// WriteArrayToFile(dumpPath, data, HOLO_SIZE, FALSE);
dprintf("Printer: C3XXusb: %s\n", __func__);
*writeSize = HOLO_SIZE;
*rResult = 0;
return 1;
}
int chcusb_setPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
switch (tagNumber) {
case 0: // setPaperInfo
memcpy(PAPERINFO, rBuffer, sizeof(PAPERINFO));
break;
case 20: // setPolishInfo
memcpy(POLISH, rBuffer, sizeof(POLISH));
break;
default:
break;
}
*rResult = 0;
return 1;
}
int chcusb_getGamma(LPCSTR filename, uint8_t *r, uint8_t *g, uint8_t *b, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
for (int i = 0; i < 256; ++i) {
r[i] = i;
g[i] = i;
b[i] = i;
}
*rResult = 0;
return 1;
}
int chcusb_getMtf(LPCSTR filename, int32_t *mtf, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
DWORD read;
uint8_t buffer[0x40];
BOOL result = ReadFile(hFile, buffer, 0x40, &read, NULL);
if (!result) return 0;
int a, c;
int b = 1;
int d = c = 0;
memset(mtf, 0, sizeof(MTF));
for (DWORD i = 0; i < read; i++) {
a = buffer[i] - 0x30;
if (a == -3 && c == 0) {
b = -1;
} else if (a >= 0 && a <= 9) {
mtf[d] = mtf[d] * 10 + a;
c++;
} else if (c > 0) {
mtf[d] *= b;
b = 1;
c = 0;
d++;
}
if (d > 9) break;
}
*rResult = 0;
return 1;
}
int chcusb_cancelCopies(uint16_t pageId, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_setPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
if ((type > 0 && type < 3) && (number > 0 && number < 3)) {
CURVE[type][number] = *data;
}
*rResult = 0;
return 1;
}
int chcusb_getPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
if ((type > 0 && type < 3) && (number > 0 && number < 3)) {
*data = CURVE[type][number];
}
*rResult = 0;
return 1;
}
int chcusb_blinkLED(uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_resetPrinter(uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rCount = 0;
*rMaxCount = 1;
return 1;
}
int chcusb_getPrintIDStatus(uint16_t pageId, uint8_t *rBuffer, uint16_t *rResult) {
// dprintf("Printer: C3XXusb: %s\n", __func__);
memset(rBuffer, 0, 8);
*((uint16_t *)(rBuffer + 6)) = 2300;
*rResult = 0;
return 1;
}
int chcusb_setPrintStandby(uint16_t position, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_testCardFeed(uint16_t mode, uint16_t times, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_exitCard(uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
awaitingCardExit = false;
generate_rfid();
*rResult = 0;
return 1;
}
int chcusb_getCardRfidTID(uint8_t *rCardTID, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
memcpy(rCardTID, cardRFID, sizeof(cardRFID));
*rResult = 2405;
return 1;
}
int chcusb_commCardRfidReader(uint8_t *sendData, uint8_t *rRecvData, uint32_t sendSize, uint32_t *rRecvSize, uint16_t *rResult) {
uint8_t off;
dprintf("Printer: C3XXusb: %s\n", __func__);
// dprintf("Printer: C3XXusb: commCardRfidReader send buffer: \n");
// dump(sendData, sendSize);
*rResult = 0;
switch (sendData[0]) {
case 0x02:
memset(rRecvData, 0, 35);
rRecvData[0] = 2;
rRecvData[2] = 32;
memcpy(rRecvData + 3, cardDataBuffer, 32);
*rRecvSize = 35;
break;
case 0x03:
off = (sendData[4] - 1) * 2;
cardDataBuffer[off] = sendData[5];
cardDataBuffer[off + 1] = sendData[6];
if (sendData[4] == 0x10) {
dprintf("Printer: C3XXusb: commCardRfidReader card data buffer: \n");
dump(cardDataBuffer, 0x20);
}
memset(rRecvData, 0, 3);
rRecvData[0] = 0x03;
*rRecvSize = 3;
break;
case 0x84:
memset(rRecvData, 0, 4);
rRecvData[0] = 0x84;
rRecvData[2] = 1;
rRecvData[3] = 0x90;
*rRecvSize = 4;
break;
case 0x85:
memset(rRecvData, 0, 12);
rRecvData[0] = 0x85;
rRecvData[2] = 9;
memcpy(rRecvData + 3, (void *)"837-15345", 9);
*rRecvSize = 12;
break;
case 0x42:
memset(rRecvData, 0, 4);
rRecvData[0] = 0x42;
rRecvData[2] = 1;
rRecvData[3] = 0x91;
*rRecvSize = 4;
break;
default:
memset(rRecvData, 0, 3);
rRecvData[0] = sendData[0];
*rRecvSize = 3;
break;
}
// dprintf("Printer: C3XXusb: commCardRfidReader recv buffer: \n");
// dump(rRecvData, *rRecvSize);
return 1;
}
int chcusb_updateCardRfidReader(uint8_t *data, uint32_t size, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_getErrorStatus(uint16_t *rBuffer) {
dprintf("Printer: C3XXusb: %s\n", __func__);
memset(rBuffer, 0, 0x80);
return 1;
}
int chcusb_setCutList(uint8_t *rData, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_setLaminatePattern(uint16_t index, uint8_t *rData, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_color_adjustment(LPCSTR filename, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_color_adjustmentEx(int32_t a1, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_getEEPROM(uint8_t index, uint8_t *rData, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_setParameter(uint8_t a1, uint32_t a2, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_getParameter(uint8_t a1, uint8_t *a2, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
int chcusb_universal_command(int32_t a1, uint8_t a2, int32_t a3, uint8_t *a4, uint16_t *rResult) {
dprintf("Printer: C3XXusb: %s\n", __func__);
*rResult = 0;
return 1;
}
// copy pasted from https://dev.s-ul.net/domeori/c310emu
#define BITMAPHEADERSIZE 0x36
DWORD ConvertDataToBitmap(
DWORD dwBitCount,
DWORD dwWidth, DWORD dwHeight,
PBYTE pbInput, DWORD cbInput,
PBYTE pbOutput, DWORD cbOutput,
PDWORD pcbResult,
bool pFlip) {
if (!pbInput || !pbOutput || dwBitCount < 8) return -3;
if (cbInput < (dwWidth * dwHeight * dwBitCount / 8)) return -3;
PBYTE pBuffer = (PBYTE)malloc(cbInput);
if (!pBuffer) return -2;
BYTE dwColors = (BYTE)(dwBitCount / 8);
if (!dwColors) return -1;
UINT16 cbColors;
RGBQUAD pbColors[256];
switch (dwBitCount) {
case 1:
cbColors = 1;
break;
case 2:
cbColors = 4;
break;
case 4:
cbColors = 16;
break;
case 8:
cbColors = 256;
break;
default:
cbColors = 0;
break;
}
if (cbColors) {
BYTE dwStep = (BYTE)(256 / cbColors);
for (UINT16 i = 0; i < cbColors; ++i) {
pbColors[i].rgbRed = dwStep * i;
pbColors[i].rgbGreen = dwStep * i;
pbColors[i].rgbBlue = dwStep * i;
pbColors[i].rgbReserved = 0;
}
}
DWORD dwTable = cbColors * sizeof(RGBQUAD);
DWORD dwOffset = BITMAPHEADERSIZE + dwTable;
// calculate the padded row size, again
DWORD dwLineSize = (dwWidth * dwBitCount / 8 + 3) & ~3;
BITMAPFILEHEADER bFile = {0};
BITMAPINFOHEADER bInfo = {0};
bFile.bfType = 0x4D42; // MAGIC
bFile.bfSize = dwOffset + cbInput;
bFile.bfOffBits = dwOffset;
bInfo.biSize = sizeof(BITMAPINFOHEADER);
bInfo.biWidth = dwWidth;
bInfo.biHeight = dwHeight;
bInfo.biPlanes = 1;
bInfo.biBitCount = (WORD)dwBitCount;
bInfo.biCompression = BI_RGB;
bInfo.biSizeImage = cbInput;
if (cbOutput < bFile.bfSize) return -1;
// Flip the image (if necessary) and add padding to each row
if (pFlip) {
for (size_t i = 0; i < dwHeight; i++) {
for (size_t j = 0; j < dwWidth; j++) {
for (size_t k = 0; k < dwColors; k++) {
// Calculate the position in the padded buffer
// Make sure to also flip the colors from RGB to BRG
size_t x = (dwHeight - i - 1) * dwLineSize + (dwWidth - j - 1) * dwColors + (dwColors - k - 1);
size_t y = (dwHeight - i - 1) * dwWidth * dwColors + j * dwColors + k;
*(pBuffer + x) = *(pbInput + y);
}
}
}
} else {
for (size_t i = 0; i < dwHeight; i++) {
for (size_t j = 0; j < dwWidth; j++) {
for (size_t k = 0; k < dwColors; k++) {
// Calculate the position in the padded buffer
size_t x = i * dwLineSize + j * dwColors + (dwColors - k - 1);
size_t y = (dwHeight - i - 1) * dwWidth * dwColors + j * dwColors + k;
*(pBuffer + x) = *(pbInput + y);
}
}
}
}
memcpy(pbOutput, &bFile, sizeof(BITMAPFILEHEADER));
memcpy(pbOutput + sizeof(BITMAPFILEHEADER), &bInfo, sizeof(BITMAPINFOHEADER));
if (cbColors) memcpy(pbOutput + BITMAPHEADERSIZE, pbColors, dwTable);
memcpy(pbOutput + dwOffset, pBuffer, cbInput);
*pcbResult = bFile.bfSize;
free(pBuffer);
return 0;
}
DWORD WriteDataToBitmapFile(
LPCWSTR lpFilePath, DWORD dwBitCount,
DWORD dwWidth, DWORD dwHeight,
PBYTE pbInput, DWORD cbInput,
PBYTE pbMetadata, DWORD cbMetadata,
bool pFlip) {
if (!lpFilePath || !pbInput) return -3;
HANDLE hFile;
DWORD dwBytesWritten;
hFile = CreateFileW(
lpFilePath,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL);
if (hFile == INVALID_HANDLE_VALUE) return -1;
// calculate the padded row size and padded image size
DWORD dwLineSize = (dwWidth * dwBitCount / 8 + 3) & ~3;
DWORD dwImageSize = dwLineSize * dwHeight;
DWORD cbResult;
DWORD cbBuffer = dwImageSize + 0x500;
PBYTE pbBuffer = (PBYTE)calloc(cbBuffer, 1);
if (!pbBuffer) return -2;
if (ConvertDataToBitmap(dwBitCount, dwWidth, dwHeight, pbInput, dwImageSize, pbBuffer, cbBuffer, &cbResult, pFlip) < 0) {
cbResult = -1;
goto WriteDataToBitmapFile_End;
}
WriteFile(hFile, pbBuffer, cbResult, &dwBytesWritten, NULL);
if (pbMetadata)
WriteFile(hFile, pbMetadata, cbMetadata, &dwBytesWritten, NULL);
CloseHandle(hFile);
cbResult = dwBytesWritten;
WriteDataToBitmapFile_End:
free(pbBuffer);
return cbResult;
}
DWORD WriteArrayToFile(LPCSTR lpOutputFilePath, LPVOID lpDataTemp, DWORD nDataSize, BOOL isAppend) {
#ifdef NDEBUG
return nDataSize;
#else
HANDLE hFile;
DWORD dwBytesWritten;
DWORD dwDesiredAccess;
DWORD dwCreationDisposition;
if (isAppend) {
dwDesiredAccess = FILE_APPEND_DATA;
dwCreationDisposition = OPEN_ALWAYS;
} else {
dwDesiredAccess = GENERIC_WRITE;
dwCreationDisposition = CREATE_ALWAYS;
}
hFile = CreateFileA(
lpOutputFilePath,
dwDesiredAccess,
FILE_SHARE_READ,
NULL,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
WriteFile(hFile, lpDataTemp, nDataSize, &dwBytesWritten, NULL);
CloseHandle(hFile);
return dwBytesWritten;
#endif
}