diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2098bea --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC=gcc +RM=rm -f +CFLAGS=-Wl,-rpath,/usr/lib -Wall -fPIC -O3 +LDFLAGS= +LDLIBS=-lcupsimage -lcups + +SRCS=rastertozj.c +OBJS=$(subst .c,.o,$(SRCS)) + +all: rastertozj + +rastertozj: $(OBJS) + gcc $(LDFLAGS) -o rastertozj rastertozj.o $(LDLIBS) + +rastertozj.o: rastertozj.c + gcc $(CFLAGS) -c rastertozj.c + diff --git a/ZJ-58.ppd b/ZJ-58.ppd new file mode 100644 index 0000000..c1362ac --- /dev/null +++ b/ZJ-58.ppd @@ -0,0 +1,113 @@ +*PPD-Adobe: "4.3" +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "zj58.ppd" +*Manufacturer: "Zijiang" +*Product: "(zj-58)" +*1284DeviceID: "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-58;CLS:PRINTER;" +*cupsVersion: 1.1 +*cupsManualCopies: True +*cupsModelNumber: 58 +*cupsFilter: "application/vnd.cups-raster 0 rastertozj" +*ModelName: "ZJ-58" +*ShortNickName: "ZJ-58" +*NickName: "Zijiang ZJ-58" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*VariablePaperSize: True +*TTRasterizer: Type42 + +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: X48MMY210MM + +*PageSize X48MMY210MM/58mm x 210mm: "<>setpagedevice" +*PageSize X48MMY297MM/58mm x 297mm: "<>setpagedevice" +*PageSize X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" + +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: X48mmY210mm + +*PageRegion X48MMY210MM/58mm x 210mm: "<>setpagedevice" +*PageRegion X48MMY297MM/58mm x 297mm: "<>setpagedevice" +*PageRegion X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" + +*DefaultImageableArea: X48MMY210MM + +*ImageableArea X48MMY210MM: "0 0 136 595" +*ImageableArea X48MMY297MM: "0 0 136 842" +*ImageableArea X48MMY3276MM: "0 0 136 9286" + +*DefaultPaperDimension: X48MMY210MM + +*PaperDimension X48MMY210MM: "136 595" +*PaperDimension X48MMY297MM: "136 842" +*PaperDimension X48MMY3276MM: "136 9286" + +*MaxMediaWidth: "136" +*MaxMediaHeight: "9286" +*HWMargins: 0 0 0 0 +*CustomPageSize True: "pop pop pop <>setpagedevice" +*ParamCustomPageSize Width: 1 points 48 136 +*ParamCustomPageSize Height: 2 points 48 9282 +*ParamCustomPageSize WidthOffset: 3 points 0 0 +*ParamCustomPageSize HeightOffset: 4 points 0 0 +*ParamCustomPageSize Orientation: 5 int 0 0 + +*OpenGroup: CutGroup/Cut Options +*OpenUI *FeedDist/Feed distance after print: PickOne +*DefaultFeedDist: 2feed9mm +*FeedDist 0feed3mm/feed 3mm: "" +*FeedDist 1feed6mm/feed 6mm: "" +*FeedDist 2feed9mm/feed 9mm: "" +*FeedDist 3feed12mm/feed 12mm: "" +*FeedDist 4feed15mm/feed 15mm: "" +*FeedDist 5feed18mm/feed 18mm: "" +*FeedDist 6feed21mm/feed 21mm: "" +*FeedDist 7feed24mm/feed 24mm: "" +*FeedDist 8feed27mm/feed 27mm: "" +*FeedDist 9feed30mm/feed 30mm: "" +*FeedDist 10feed33mm/feed 33mm: "" +*FeedDist 11feed36mm/feed 36mm: "" +*FeedDist 12feed39mm/feed 39mm: "" +*FeedDist 13feed42mm/feed 42mm: "" +*FeedDist 14feed45mm/feed 45mm: "" +*CloseUI: *FeedDist + + +*OpenUI *BlankSpace/Blank space at page's end: PickOne +*DefaultBlankSpace: 1NoPrint +*BlankSpace 0Print/Print: "" +*BlankSpace 1NoPrint/Do not print: "" +*CloseUI: *BlankSpace + +*CloseGroup: *CutGroup + +*OpenGroup: *CashDrawerGroup/Cash Drawer Control +*OpenUI *CashDrawer1Setting/Cash Drawer 1: PickOne +*DefaultCashDrawer1Setting: 0NotCashDrawer1 +*CashDrawer1Setting 0NotCashDrawer1/Not Cash Drawer 1: "" +*CashDrawer1Setting 1NotCashDrawer1BeforePrinting/Cash Drawer 1 Before Printing: "" +*CashDrawer1Setting 2NotCashDrawer1BeforePrinting/Cash Drawer 1 After Printing: "" +*CloseUI: *CashDrawer1Setting + +*OpenUI *CashDrawer2Setting/Cash Drawer 2: PickOne +*DefaultCashDrawer2Setting: 0NotCashDrawer2 +*CashDrawer2Setting 0NotCashDrawer2/Not Cash Drawer 2: "" +*CashDrawer2Setting 1NotCashDrawer2BeforePrinting/Cash Drawer 2 Before Printing: "" +*CashDrawer2Setting 2NotCashDrawer2BeforePrinting/Cash Drawer 2 After Printing: "" +*CloseUI: *CashDrawer2Setting +*CloseGroup: *CashDrawerGroup + + +*% End diff --git a/install b/install new file mode 100755 index 0000000..6fc0a5d --- /dev/null +++ b/install @@ -0,0 +1,13 @@ +#!/bin/bash + +# Installs zj-58 driver +# Tested as working under Ubuntu 14.04 + +/etc/init.d/cups stop +cp rastertozj /usr/lib/cups/filter/ +cp ZJ-58.ppd /usr/share/cups/model/zjiang/ +cd /usr/lib/cups/filter +chmod 755 rastertozj +chown root:root rastertozj +cd - +/etc/init.d/cups start diff --git a/rastertozj b/rastertozj new file mode 100755 index 0000000..9538f2a Binary files /dev/null and b/rastertozj differ diff --git a/rastertozj.c b/rastertozj.c new file mode 100644 index 0000000..6f09788 --- /dev/null +++ b/rastertozj.c @@ -0,0 +1,353 @@ +/* + * Include necessary headers... + */ + +// To get required headers, run +// sudo apt-get install libcups2-dev libcupsimage2-dev +#include +#include +#include +#include +#include +#include + +#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) ) + +// uncomment next line in order to have verbose dump in DEBUGFILE +// after print + +//#define DEBUGP + +#define DEBUGFILE "/tmp/debugraster.txt" + +#define FALSE 0 +#define TRUE (!FALSE) + +struct settings_ +{ + int cashDrawer1; + int cashDrawer2; + int blankSpace; + int feedDist; +}; + +struct command +{ + int length; + char* command; +}; + +// define printer initialize command +static const struct command printerInitializeCommand = +{2,(char[2]){0x1b,0x40}}; + +// define cashDrawerEjector command +static const struct command cashDrawerEject [2] = +{{5,(char[5]){0x1b,0x70,0,0x40,0x50}}, + {5,(char[5]){0x1b,0x70,1,0x40,0x50}}}; + +// define raster mode start command +static const struct command rasterModeStartCommand = +{4,(char[4]){0x1d,0x76,0x30,0}}; + +// define raster flush command +static const struct command rasterModeFlushCommand = +{3,(char[3]){0x1b,0x4a,0x15}}; + +#ifdef DEBUGP +FILE* lfd = 0; +#endif + +inline void mputchar(char c) +{ + unsigned char m = c; +#ifdef DEBUGP + if (lfd) + fprintf (lfd,"%02x ",m); +#endif + putchar(m); +} + + +inline void outputarray(const char * array, int length) +{ +int i = 0; +for (;i>8); +} + +inline void rasterheader(int xsize, int ysize) +{ +outputCommand(rasterModeStartCommand); +mputchar(lo(xsize)); +mputchar(hi(xsize)); +mputchar(lo(ysize)); +mputchar(hi(ysize)); +} + +inline void skiplines(int size) +{ mputchar(0x1b); +mputchar(0x4a); +mputchar(size); +} + +inline int getOptionChoiceIndex(const char * choiceName, ppd_file_t * ppd) +{ +ppd_choice_t * choice; +ppd_option_t * option; + +choice = ppdFindMarkedChoice(ppd, choiceName); + +if (choice == NULL) +{ + if ((option = ppdFindOption(ppd, choiceName)) == NULL) return -1; + if ((choice = ppdFindChoice(option,option->defchoice)) == NULL) return -1; +} + +return atoi(choice->choice); +} + +struct settings_ settings; + +inline void initializeSettings(char * commandLineOptionSettings) +{ +ppd_file_t * ppd = NULL; +cups_option_t * options = NULL; +int numOptions = 0; + +ppd = ppdOpenFile(getenv("PPD")); + +ppdMarkDefaults(ppd); + +numOptions = cupsParseOptions(commandLineOptionSettings, 0, &options); +if ((numOptions != 0) && (options != NULL)) +{ + cupsMarkOptions(ppd, numOptions, options); + cupsFreeOptions(numOptions, options); +} + +memset(&settings, 0x00, sizeof(struct settings_)); + + settings.cashDrawer1 = getOptionChoiceIndex("CashDrawer1Setting", ppd); + settings.cashDrawer2 = getOptionChoiceIndex("CashDrawer2Setting", ppd); + settings.blankSpace = getOptionChoiceIndex("BlankSpace" , ppd); + settings.feedDist = getOptionChoiceIndex("FeedDist" , ppd); + + ppdClose(ppd); +} + +void jobSetup() +{ + if ( settings.cashDrawer1==1 ) + outputCommand(cashDrawerEject[0]); + if ( settings.cashDrawer2==1 ) + outputCommand(cashDrawerEject[1]); + outputCommand(printerInitializeCommand); +} + +void ShutDown() +{ + if ( settings.cashDrawer1==2 ) + outputCommand(cashDrawerEject[0]); + if ( settings.cashDrawer2==2 ) + outputCommand(cashDrawerEject[1]); + outputCommand(printerInitializeCommand); +} + +int num_of_feed; + +void EndPage() +{ + int i; + for (i=0; i 7) + { + fputs("ERROR: rastertozj58 job-id user title copies options [file]\n", stderr); + return EXIT_FAILURE; + } + + if (argc == 7) + { + if ((fd = open(argv[6], O_RDONLY)) == -1) + { + perror("ERROR: Unable to open raster file - "); + sleep(1); + + return EXIT_FAILURE; + } + } + else + fd = 0; +#ifdef DEBUGP + lfd = fopen ("/tmp/raster.txt","w"); +#endif + initializeSettings(argv[5]); + + jobSetup(); + ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + page = 0; + + while (cupsRasterReadHeader2(ras, &header)) + { + if ((header.cupsHeight == 0) || (header.cupsBytesPerLine == 0)) + break; + +#ifdef DEBUGP + if (lfd) fprintf(lfd,"\nheader.cupsHeight=%d, header.cupsBytesPerLine=%d\n",header.cupsHeight,header.cupsBytesPerLine); +#endif + + if (rasterData == NULL) + { + rasterData = malloc(header.cupsBytesPerLine*24); + if (rasterData == NULL) + { + if (originalRasterDataPtr != NULL) free(originalRasterDataPtr); + cupsRasterClose(ras); + if (fd != 0) + close(fd); + return EXIT_FAILURE; + + } + originalRasterDataPtr = rasterData; // used to later free the memory + } + + + fprintf(stderr, "PAGE: %d %d\n", ++page, header.NumCopies); + pageSetup(); + + int foo = ( header.cupsWidth > 0x180 ) ? 0x180 : header.cupsWidth; + foo = (foo+7) & 0xFFFFFFF8; + int width_size = foo >> 3; + + +#ifdef DEBUGP + if (lfd) fprintf(lfd,"\nheader.cupsWidth=%d, foo=%d, width_size=%d\n",header.cupsWidth,foo,width_size); +#endif + y = 0; + int zeroy = 0; + + while ( y < header.cupsHeight ) + { + if ((y & 127) != 0) + fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", page, (100 * y / header.cupsHeight)); + + int rest = header.cupsHeight-y; + if (rest>24) + rest=24; + +#ifdef DEBUGP + if (lfd) fprintf(lfd,"\nProcessing block of %d, starting from %d lines\n",rest,y); +#endif + y+=rest; + + if (y) + { + unsigned char * buf = rasterData; + int j; + for ( j=0; j=rest_bytes) + { + ++zeroy; + continue; + } + + for (;zeroy>0;--zeroy) + skiplines(24); + + rasterheader(width_size,rest); + outputarray((char*)rasterData,width_size*24); + skiplines(0); + } + + if (!settings.blankSpace) + for(;zeroy>0;--zeroy) + skiplines(24); + + EndPage(); + } + + ShutDown(); + + if (originalRasterDataPtr != NULL) free(originalRasterDataPtr); + cupsRasterClose(ras); + if (fd != 0) + close(fd); + + if (page == 0) + fputs("ERROR: No pages found!\n", stderr); + else + fputs("INFO: Ready to print.\n", stderr); +#ifdef DEBUGP + if (lfd) + fclose(lfd); +#endif + return (page == 0)?EXIT_FAILURE:EXIT_SUCCESS; +} + +// end of rastertostar.c