forked from Hay1tsme/segatools
		
	
		
			
				
	
	
		
			2381 lines
		
	
	
		
			68 KiB
		
	
	
	
		
			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
 | |
| }
 |