mirror of
				https://git.familie-radermacher.ch/linux/ptouch-print.git
				synced 2025-10-31 12:22:44 +00:00 
			
		
		
		
	fix support for printers that use packbits transfer mode, like PT-D450PV
This commit is contained in:
		
							parent
							
								
									1c552a3d11
								
							
						
					
					
						commit
						213a70eee0
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -9,6 +9,7 @@ Makefile.in | ||||
| /install-sh | ||||
| /missing | ||||
| /stamp-h1 | ||||
| /configure | ||||
| /config.guess | ||||
| /config.h.in | ||||
| /config.rpath | ||||
|  | ||||
							
								
								
									
										3
									
								
								autogen.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								autogen.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,3 @@ | ||||
| #!/bin/sh | ||||
| rm -rf autom4te.cache configure config.* | ||||
| autoreconf --install || exit 1 | ||||
							
								
								
									
										3
									
								
								build-aux/git-version-gen
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								build-aux/git-version-gen
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,3 @@ | ||||
| #!/bin/sh | ||||
| GIT_VERSION=$(git --no-pager describe --tags --dirty |sed 's/\([^-]*-g\)/r\1/;s/-/./g;s/v//g') | ||||
| echo -ne ${GIT_VERSION} | ||||
| @ -20,7 +20,7 @@ | ||||
| # Process this file with autoconf to produce a configure script. | ||||
| 
 | ||||
| AC_PREREQ([2.69]) | ||||
| AC_INIT([ptouch], [1.3.3], [blip@mockmoon-cybernetics.ch]) | ||||
| AC_INIT([ptouch], [m4_esyscmd_s([build-aux/git-version-gen])], [blip@mockmoon-cybernetics.ch]) | ||||
| AC_CONFIG_SRCDIR([src/libptouch.c]) | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /*
 | ||||
| 	ptouch-print - Print labels with images or text on a Brother P-Touch | ||||
| 	 | ||||
| 	Copyright (C) 2015-2017 Dominic Radermacher <blip@mockmoon-cybernetics.ch> | ||||
| 	Copyright (C) 2015-2019 Dominic Radermacher <blip@mockmoon-cybernetics.ch> | ||||
| 
 | ||||
| 	This program is free software; you can redistribute it and/or modify it | ||||
| 	under the terms of the GNU General Public License version 3 as | ||||
| @ -25,8 +25,10 @@ struct _pt_tape_info { | ||||
| 	uint8_t px;		/* Printing area in px */ | ||||
| }; | ||||
| 
 | ||||
| #define FLAG_NONE		0 | ||||
| #define FLAG_UNSUP_RASTER	1 | ||||
| #define FLAG_NONE		(0x00) | ||||
| #define FLAG_UNSUP_RASTER	(0x01) | ||||
| #define FLAG_RASTER_PACKBITS	(0x02) | ||||
| 
 | ||||
| struct _pt_dev_info { | ||||
| 	int vid;		/* USB vendor ID */ | ||||
| 	int pid;		/* USB product ID */ | ||||
| @ -36,14 +38,40 @@ struct _pt_dev_info { | ||||
| }; | ||||
| typedef struct _pt_dev_info *pt_dev_info; | ||||
| 
 | ||||
| struct __attribute__((packed, aligned(4))) _ptouch_stat { | ||||
| 	uint8_t printheadmark;	// 0x80
 | ||||
| 	uint8_t size;		// 0x20
 | ||||
| 	uint8_t brother_code;	// "B"
 | ||||
| 	uint8_t series_code;	// "0"
 | ||||
| 	uint8_t model; | ||||
| 	uint8_t country;	// "0"
 | ||||
| 	uint16_t reserved_1; | ||||
| 	uint16_t error;		// table 1 and 2
 | ||||
| 	uint8_t media_width;	// tape width in mm
 | ||||
| 	uint8_t media_type;	// table 4
 | ||||
| 	uint8_t ncol;		// 0
 | ||||
| 	uint8_t fonts;		// 0
 | ||||
| 	uint8_t jp_fonts;	// 0
 | ||||
| 	uint8_t mode; | ||||
| 	uint8_t density;	// 0
 | ||||
| 	uint8_t media_len;	// table length, always 0
 | ||||
| 	uint8_t status_type;	// table 5
 | ||||
| 	uint8_t phase_type; | ||||
| 	uint16_t phase_number;	// table 6
 | ||||
| 	uint8_t notif_number; | ||||
| 	uint8_t exp;		// 0
 | ||||
| 	uint8_t tape_color;	// table 8
 | ||||
| 	uint8_t text_color;	// table 9
 | ||||
| 	uint32_t hw_setting; | ||||
| 	uint16_t reserved_2; | ||||
| }; | ||||
| typedef struct _ptouch_stat *pt_dev_stat; | ||||
| 
 | ||||
| struct _ptouch_dev { | ||||
| 	libusb_device_handle *h; | ||||
| 	uint8_t raw[32]; | ||||
| 	uint8_t tape_width_mm; | ||||
| 	uint8_t tape_width_px; | ||||
| 	uint8_t status; | ||||
| 	uint8_t media_type; | ||||
| 	pt_dev_info devinfo; | ||||
| 	pt_dev_stat status; | ||||
| 	uint8_t tape_width_px; | ||||
| }; | ||||
| typedef struct _ptouch_dev *ptouch_dev; | ||||
| 
 | ||||
| @ -57,5 +85,6 @@ int ptouch_cutmark(ptouch_dev ptdev); | ||||
| int ptouch_eject(ptouch_dev ptdev); | ||||
| int ptouch_getstatus(ptouch_dev ptdev); | ||||
| int ptouch_getmaxwidth(ptouch_dev ptdev); | ||||
| int ptouch_enable_packbits(ptouch_dev ptdev); | ||||
| int ptouch_rasterstart(ptouch_dev ptdev); | ||||
| int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, int len); | ||||
|  | ||||
| @ -32,24 +32,27 @@ | ||||
| 
 | ||||
| #define _(s) gettext(s) | ||||
| 
 | ||||
| struct _pt_tape_info tape_info[6]= { | ||||
| 	{6, 32},	/* 6mm tape is 32px wide? works for me ;-) */ | ||||
| 	{9, 52},	/* 9mm tape is 52px wide? works for me ;-) */ | ||||
| 	{12,76},	/* and 76px work for me on a 12mm tape - maybe its only 64px */ | ||||
| 	{18,120}, | ||||
| 	{24,128}, | ||||
| 	{0,0}		/* terminating entry */ | ||||
| /* Print area width in 180 DPI pixels */ | ||||
| struct _pt_tape_info tape_info[]= { | ||||
| 	{ 6, 32},	/* 6 mm tape */ | ||||
| 	{ 9, 52},	/* 9 mm tape */ | ||||
| 	{12, 76},	/* 12 mm tape */ | ||||
| 	{18, 120},	/* 18 mm tape */ | ||||
| 	{24, 128},	/* 24 mm tape */ | ||||
| 	{36, 192},	/* 36 mm tape */ | ||||
| 	{ 0, 0}		/* terminating entry */ | ||||
| }; | ||||
| 
 | ||||
| struct _pt_dev_info ptdevs[] = { | ||||
| 	{0x04f9, 0x202d, "PT-2430PC", 128, FLAG_NONE},	/* 180dpi, maximum 128px */ | ||||
| 	{0x04f9, 0x2031, "PT-2430PC", 128, FLAG_SWITCH_WRONG},  /* */ | ||||
| 	{0x04f9, 0x202c, "PT-1230PC", 76, FLAG_NONE},	/* 180dpi, supports tapes up to 12mm - I don't know how much pixels it can print! */ | ||||
| 	{0x04f9, 0x202d, "PT-2430PC", 128, FLAG_NONE},		/* 180dpi, maximum 128px */ | ||||
| 	{0x04f9, 0x2007, "PT-2420PC", 128, FLAG_RASTER_PACKBITS},	/* 180dpi, 128px, maximum tape width 24mm, must send TIFF compressed pixel data */ | ||||
| 	{0x04f9, 0x202c, "PT-1230PC", 76, FLAG_NONE},		/* 180dpi, supports tapes up to 12mm - I don't know how much pixels it can print! */ | ||||
| 	{0x04f9, 0x2061, "PT-P700", 120, FLAG_UNSUP_RASTER},	/* DOES NOT WORK */ | ||||
| 	{0x04f9, 0x2073, "PT-D450VP", 120, FLAG_UNSUP_RASTER},	/* DOES NOT WORK */ | ||||
| 	/* Notes about the PT-D450VP: Tape detecting works, but printing does
 | ||||
| 	   not. The tape is just blank. I assume, the printer does not understand | ||||
| 	   the sent rasterdata. I'm also unsure about how many dots width we have */ | ||||
| 	{0x04f9, 0x2073, "PT-D450VP", 128, FLAG_RASTER_PACKBITS}, | ||||
| 	/* Notes about the PT-D450VP: I'm unsure if print width really is 128px */ | ||||
| 	{0x04f9, 0x2041, "PT-2730PC", 128, FLAG_NONE},		/* 180dpi, maximum 128px, max tape width 24mm - reported to work with some quirks */ | ||||
| 	/* Notes about the PT-2730PC: was reported to need 48px whitespace
 | ||||
| 	   within png-images before content is actually printed - can not check this */ | ||||
| 	{0,0,"",0,0} | ||||
| }; | ||||
| 
 | ||||
| @ -72,6 +75,10 @@ int ptouch_open(ptouch_dev *ptdev) | ||||
| 		fprintf(stderr, _("out of memory\n")); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (((*ptdev)->status=malloc(sizeof(struct _ptouch_stat))) == NULL) { | ||||
| 		fprintf(stderr, _("out of memory\n")); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if ((libusb_init(NULL)) < 0) { | ||||
| 		fprintf(stderr, _("libusb_init() failed\n")); | ||||
| 		return -1; | ||||
| @ -149,9 +156,15 @@ int ptouch_init(ptouch_dev ptdev) | ||||
| 	return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd)); | ||||
| } | ||||
| 
 | ||||
| int ptouch_enable_packbits(ptouch_dev ptdev) | ||||
| {				/* 4D 00 = disable compression */ | ||||
| 	char cmd[] = "M\x02";	/* 4D 02 = enable packbits compression mode */ | ||||
| 	return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd)); | ||||
| } | ||||
| 
 | ||||
| int ptouch_rasterstart(ptouch_dev ptdev) | ||||
| { | ||||
| 	char cmd[]="\x1b\x69\x52\x01";	/* 1B 69 52 01 = RASTER DATA */ | ||||
| 	char cmd[] = "\x1b\x69\x52\x01";	/* 1B 69 52 01 = Select graphics transfer mode = Raster */ | ||||
| 	return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd)); | ||||
| } | ||||
| 
 | ||||
| @ -219,7 +232,7 @@ void ptouch_rawstatus(uint8_t raw[32]) | ||||
| 
 | ||||
| int ptouch_getstatus(ptouch_dev ptdev) | ||||
| { | ||||
| 	char cmd[]="\x1b\x69\x53"; | ||||
| 	char cmd[]="\x1biS";	/* 1B 69 53 = ESC i S = Status info request */ | ||||
| 	uint8_t buf[32]; | ||||
| 	int i, r, tx=0, tries=0; | ||||
| 	struct timespec w; | ||||
| @ -241,14 +254,7 @@ int ptouch_getstatus(ptouch_dev ptdev) | ||||
| 	} | ||||
| 	if (tx == 32) { | ||||
| 		if (buf[0]==0x80 && buf[1]==0x20) { | ||||
| 			memcpy(ptdev->raw, buf, 32); | ||||
| 			if (buf[8] != 0) { | ||||
| 				fprintf(stderr, _("Error 1 = %02x\n"), buf[8]); | ||||
| 			} | ||||
| 			if (buf[9] != 0) { | ||||
| 				fprintf(stderr, _("Error 2 = %02x\n"), buf[9]); | ||||
| 			} | ||||
| 			ptdev->tape_width_mm=buf[10]; | ||||
| 			memcpy(ptdev->status, buf, 32); | ||||
| 			ptdev->tape_width_px=0; | ||||
| 			for (i=0; tape_info[i].mm > 0; i++) { | ||||
| 				if (tape_info[i].mm == buf[10]) { | ||||
| @ -258,8 +264,6 @@ int ptouch_getstatus(ptouch_dev ptdev) | ||||
| 			if (ptdev->tape_width_px == 0) { | ||||
| 				fprintf(stderr, _("unknown tape width of %imm, please report this.\n"), buf[10]); | ||||
| 			} | ||||
| 			ptdev->media_type=buf[11]; | ||||
| 			ptdev->status=buf[18]; | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| @ -284,21 +288,31 @@ int ptouch_getstatus(ptouch_dev ptdev) | ||||
| 
 | ||||
| int ptouch_getmaxwidth(ptouch_dev ptdev) | ||||
| { | ||||
| 	/* TODO: should also check what the device supports. but I assume,
 | ||||
| 	   you can't use a large tape in a printe that doesn't support it anyways */ | ||||
| 	return ptdev->tape_width_px; | ||||
| } | ||||
| 
 | ||||
| int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, int len) | ||||
| { | ||||
| 	uint8_t buf[32]; | ||||
| 	uint8_t buf[70]; | ||||
| 	int rc; | ||||
| 
 | ||||
| 	if (len > ptdev->devinfo->max_px / 8) { | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (len > 16) {		/* PT-2430PC can not print more than 128 px */ | ||||
| 		return -1;	/* as we support more devices, we need to check */ | ||||
| 	}			/* how much pixels each device support */ | ||||
| 	buf[0]=0x47; | ||||
| 	buf[1]=len; | ||||
| 	buf[2]=0; | ||||
| 	memcpy(buf+3, data, len); | ||||
| 	return ptouch_send(ptdev, buf, len+3); | ||||
| 	if (ptdev->devinfo->flags & FLAG_RASTER_PACKBITS) { | ||||
| 	        /* Fake compression by encoding a single uncompressed run */ | ||||
| 	        buf[1] = len + 1; | ||||
| 	        buf[2] = 0; | ||||
| 	        buf[3] = len - 1; | ||||
| 	        memcpy(buf + 4, data, len); | ||||
| 	        rc = ptouch_send(ptdev, buf, len + 4); | ||||
| 	} else { | ||||
| 		buf[1] = len; | ||||
| 		buf[2] = 0; | ||||
| 		memcpy(buf + 3, data, len); | ||||
| 		rc = ptouch_send(ptdev, buf, len + 3); | ||||
| 	} | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /*
 | ||||
| 	ptouch-print - Print labels with images or text on a Brother P-Touch | ||||
| 	 | ||||
| 	Copyright (C) 2015-2017 Dominic Radermacher <blip@mockmoon-cybernetics.ch> | ||||
| 	Copyright (C) 2015-2019 Dominic Radermacher <blip@mockmoon-cybernetics.ch> | ||||
| 
 | ||||
| 	This program is free software; you can redistribute it and/or modify it | ||||
| 	under the terms of the GNU General Public License version 3 as | ||||
| @ -71,6 +71,10 @@ int print_img(ptouch_dev ptdev, gdImage *im) | ||||
| 	int d,i,k,offset,tape_width; | ||||
| 	uint8_t rasterline[16]; | ||||
| 
 | ||||
| 	if (!im) { | ||||
| 		printf(_("nothing to print\n")); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if ((ptdev->devinfo->flags & FLAG_UNSUP_RASTER) == FLAG_UNSUP_RASTER) { | ||||
| 		unsupported_printer(ptdev); | ||||
| 	} | ||||
| @ -83,6 +87,10 @@ int print_img(ptouch_dev ptdev, gdImage *im) | ||||
| 		return -1; | ||||
| 	} | ||||
| 	offset=64-(gdImageSY(im)/2);	/* always print centered  */ | ||||
| 	if ((ptdev->devinfo->flags & FLAG_RASTER_PACKBITS) == FLAG_RASTER_PACKBITS) { | ||||
| 		printf("enable PackBits mode\n"); | ||||
| 	        ptouch_enable_packbits(ptdev); | ||||
| 	} | ||||
| 	if (ptouch_rasterstart(ptdev) != 0) { | ||||
| 		printf(_("ptouch_rasterstart() failed\n")); | ||||
| 		return -1; | ||||
| @ -95,7 +103,7 @@ int print_img(ptouch_dev ptdev, gdImage *im) | ||||
| 			} | ||||
| 		} | ||||
| 		if (ptouch_sendraster(ptdev, rasterline, 16) != 0) { | ||||
| 			printf(_("ptouch_send() failed\n")); | ||||
| 			printf(_("ptouch_sendraster() failed\n")); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| @ -319,7 +327,7 @@ int parse_args(int argc, char **argv) | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| 	int i, lines, tape_width; | ||||
| 	int i, lines = 0, tape_width; | ||||
| 	char *line[MAX_LINES]; | ||||
| 	gdImage *im=NULL; | ||||
| 	ptouch_dev ptdev=NULL; | ||||
| @ -366,13 +374,14 @@ int main(int argc, char *argv[]) | ||||
| 			} | ||||
| 		} else if (strcmp(&argv[i][1], "-info") == 0) { | ||||
| 			printf(_("maximum printing width for this tape is %ipx\n"), tape_width); | ||||
| 			printf("media type = %02x\n", ptdev->status->media_type); | ||||
| 			printf("media width = %d mm\n", ptdev->status->media_width); | ||||
| 			printf("tape color = %02x\n", ptdev->status->tape_color); | ||||
| 			printf("text color = %02x\n", ptdev->status->text_color); | ||||
| 			printf("error = %04x\n", ptdev->status->error); | ||||
| 			exit(0); | ||||
| 		} else if (strcmp(&argv[i][1], "-image") == 0) { | ||||
| 			im=image_load(argv[++i]); | ||||
| 			if (im != NULL) { | ||||
| 				print_img(ptdev, im); | ||||
| 				gdImageDestroy(im); | ||||
| 			} | ||||
| 		} else if (strcmp(&argv[i][1], "-text") == 0) { | ||||
| 			for (lines=0; (lines < MAX_LINES) && (i < argc); lines++) { | ||||
| 				if ((i+1 >= argc) || (argv[i+1][0] == '-')) { | ||||
| @ -381,25 +390,31 @@ int main(int argc, char *argv[]) | ||||
| 				i++; | ||||
| 				line[lines]=argv[i]; | ||||
| 			} | ||||
| 			if ((im=render_text(font_file, line, lines, tape_width)) == NULL) { | ||||
| 				printf(_("could not render text\n")); | ||||
| 				return 1; | ||||
| 			} | ||||
| 			if (save_png != NULL) { | ||||
| 				write_png(im, save_png); | ||||
| 			} else { | ||||
| 				print_img(ptdev, im); | ||||
| 			} | ||||
| 			gdImageDestroy(im); | ||||
| 		} else if (strcmp(&argv[i][1], "-cutmark") == 0) { | ||||
| 			ptouch_cutmark(ptdev); | ||||
| 		} else { | ||||
| 			usage(argv[0]); | ||||
| 		} | ||||
| 	} | ||||
| 	if (ptouch_eject(ptdev) != 0) { | ||||
| 		printf(_("ptouch_eject() failed\n")); | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (lines) { | ||||
| 		if ((im=render_text(font_file, line, lines, tape_width)) == NULL) { | ||||
| 			printf(_("could not render text\n")); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (im) { | ||||
| 		if (save_png) { | ||||
| 			write_png(im, save_png); | ||||
| 		} else { | ||||
| 			print_img(ptdev, im); | ||||
| 			if (ptouch_eject(ptdev) != 0) { | ||||
| 				printf(_("ptouch_eject() failed\n")); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 		gdImageDestroy(im); | ||||
| 	} | ||||
| 	ptouch_close(ptdev); | ||||
| 	libusb_exit(NULL); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dominic Radermacher
						Dominic Radermacher