mirror of
https://git.familie-radermacher.ch/linux/ptouch-print.git
synced 2025-05-13 15:22:56 +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…
Reference in New Issue
Block a user