1 /* esc-m.c - try to parse minolta pagepro 1200 w printer data files
2 *
3 * Copyright (C) 2004, 2005 Manuel Tobias Schiller <mala@hinterbergen.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 /*
20 * this little program was meant to make understanding the output
21 * of the printer driver easier. i guess it might sometimes still
22 * be useful...
23 *
24 * this is a quick and _dirty_ hack based on looking at the windoze
25 * driver output and some of the windoze driver plaintext files
26 * (most notably msdmlt_c.sdd for the paper format codes - this
27 * file might contain other valuable information I do not understand
28 * yet...)
29 *
30 * this thing may or may not provide you with accurate information
31 * the purpose of some of the data sent to the printer is still not
32 * understood - have a look at format.txt and look for entries which
33 * do not satisfy a curious mind...
34 * the raster data is hex dumped by this utility
35 */
36
37 #include <stdio.h>
38
39 /* file position ans sequence number */
40 static int i = 0, sq = 0;
41 /* current resolution */
42 static int gl_res = -1, gl_res_h = -1;
43 /* page dimensions in dots at current resolution */
44 static int gl_x, gl_y;
45 /* paper tray */
46 static int gl_tray = -1;
47 /* paper format */
48 static int gl_pformat = -1;
49
getdword(unsigned char * data)50 static int getdword(unsigned char *data)
51 {
52 int retVal;
53
54 retVal = ((int) data[1]) << 24;
55 retVal |= ((int) data[0]) << 16;
56 retVal |= ((int) data[3]) << 8;
57 retVal |= ((int) data[2]);
58
59 return retVal;
60 }
61
dumpraw(unsigned char * data)62 static void dumpraw(unsigned char *data)
63 {
64 int tmp, lb;
65 /* raw data dump */
66 printf("ESC %02x: raw data dump:", data[1]);
67
68 lb = data[3];
69 data += 6;
70
71 for (tmp = 0; tmp < lb; tmp++) {
72 if ((tmp & 0xf) == 0) printf("\n\t");
73 printf("%02x ", (int) *data++);
74 }
75 printf("\n\n");
76 }
77
dump50(unsigned char * data)78 static void dump50(unsigned char *data)
79 {
80 char *res, *ptype, *rmstr;
81 unsigned char r, p, rm;
82 int lb;
83
84 lb = data[3];
85
86 /* dump ESC 50 data */
87 printf("ESC 50: select resolution and paper type:\n");
88
89 if (lb != 8) {
90 printf("\tExpected 8 data bytes for ESC 0x50 command, recieved %d.\n", lb);
91 dumpraw(data);
92 return;
93 }
94 /* we dump the raw data nevertheless to make is easier to spot
95 * format changes when Minolta introduces a new model... */
96 dumpraw(data);
97
98 data += 6;
99
100 switch (r = *data++) {
101 case 0:
102 res = "300 dpi"; gl_res = 300;
103 break;
104 case 1:
105 res = "600 dpi"; gl_res = 600;
106 break;
107 case 2:
108 res = "1200 dpi"; gl_res = 1200;
109 break;
110 default:
111 res = "unknown"; gl_res = -1;
112 break;
113 }
114 switch (rm = *data++) {
115 case 0:
116 rmstr = "none";
117 gl_res_h = gl_res;
118 break;
119 case 1:
120 rmstr = "double horizontal resolution";
121 gl_res_h = gl_res * 2;
122 break;
123 default:
124 rmstr = "unknown horizontal resolution modifier";
125 gl_res_h = -1;
126 break;
127 }
128 data += 1; /* next two bytes seem to be don't care data */
129 switch (p = *data++) {
130 case 0:
131 ptype = "normal paper";
132 break;
133 case 1:
134 ptype = "thick paper";
135 break;
136 case 2:
137 ptype = "transparency";
138 break;
139 case 3:
140 ptype = "envelope/postcard";
141 break;
142 default:
143 ptype = "unknown paper";
144 break;
145 }
146 /* next four bytes seem to be don't care data */
147
148 printf("\tresolution code %02x (%s)\n", r, res);
149 printf("\thorizontal resolution modifier: %02x (%s)\n", rm, rmstr);
150 printf("\teffective resolution is %d x %d dpi\n", gl_res_h, gl_res);
151 printf("\tpaper code %02x (%s)\n\n", p, ptype);
152 }
153
dump51(unsigned char * data)154 static void dump51(unsigned char *data)
155 {
156 unsigned char lb;
157 char *tray, *pformat;
158
159 lb = data[3];
160
161 /* dump ESC 51 data */
162 printf("ESC 51: start new page and set paper format:\n");
163
164 if (lb != 22) {
165 printf("\tExpected 22 data bytes for ESC 0x51 command, recieved %d.\n", lb);
166 dumpraw(data);
167 return;
168 }
169 /* we dump the raw data nevertheless to make is easier to spot
170 * format changes when Minolta introduces a new model... */
171 dumpraw(data);
172 data += 6;
173
174 data += 2; /* seems to be don't care data */
175 gl_x = getdword(data); data += 4;
176 gl_y = getdword(data); data += 4;
177 data += 4; /* seems to be don't care data */
178 switch (gl_tray = *data++) {
179 case 0xff:
180 tray = "auto"; break;
181 case 0x00:
182 tray = "tray 1"; break;
183 case 0x01:
184 tray = "tray 2"; break;
185 case 0x80:
186 tray = "manual feed"; break;
187 default:
188 tray = "unknown"; break;
189 }
190 switch (gl_pformat = *data) {
191 default:
192 pformat = "unknown"; break;
193 case 0x04:
194 pformat = "a4"; break;
195 case 0x06:
196 pformat = "b5"; break;
197 case 0x08:
198 pformat = "a5"; break;
199 case 0x0c:
200 pformat = "j-post"; break;
201 case 0x0d:
202 pformat = "cor. post"; break;
203 case 0x10:
204 pformat = "jis y6"; break;
205 case 0x11:
206 pformat = "jis y0"; break;
207 case 0x13:
208 pformat = "chinese 16k"; break;
209 case 0x15:
210 pformat = "chinese 32k"; break;
211 case 0x19:
212 pformat = "legal"; break;
213 case 0x1a:
214 pformat = "g. legal"; break;
215 case 0x1b:
216 pformat = "letter"; break;
217 case 0x1d:
218 pformat = "g. letter"; break;
219 case 0x1f:
220 pformat = "executive"; break;
221 case 0x21:
222 pformat = "half letter"; break;
223 case 0x24:
224 pformat = "env monarch"; break;
225 case 0x25:
226 pformat = "env #10"; break;
227 case 0x26:
228 pformat = "env dl"; break;
229 case 0x27:
230 pformat = "env c5"; break;
231 case 0x28:
232 pformat = "env c6"; break;
233 case 0x29:
234 pformat = "env b5"; break;
235 case 0x2d:
236 pformat = "choukei-3gou"; break;
237 case 0x2e:
238 pformat = "choukei-4gou"; break;
239 case 0x31:
240 pformat = "custom"; break;
241 }
242 /* rest seems to be don't care data... */
243
244 printf("\tpaper format is %02x (%s).\n", gl_pformat, pformat);
245 printf("\tpage size is %d x %d dots (%.3lf x %.3lf \" or %.2lf x %.2lf mm).\n",
246 gl_x, gl_y,
247 (double) gl_x / (double) gl_res_h,
248 (double) gl_y / (double) gl_res,
249 25.4 * (double) gl_x / (double) gl_res_h,
250 25.4 * (double) gl_y / (double) gl_res);
251 printf("\tpaper tray id %02x (%s)\n\n", gl_tray, tray);
252 }
253
dump52(unsigned char * data)254 static void dump52(unsigned char *data)
255 {
256 int tmp2, tmp;
257 unsigned char lb = data[3];
258
259 /* dump ESC 52 data */
260 printf("ESC 52: send raster data:\n");
261
262 if (lb != 6) {
263 printf("\tExpected 6 data bytes for ESC 0x52 command, recieved %d.\n", lb);
264 dumpraw(data);
265 return;
266 }
267 data += 6;
268
269 /* copy further data bytes */
270 /* get length out of data array */
271 tmp2 = data[3]; tmp2 <<= 8;
272 tmp2 |= data[2]; tmp2 <<= 8;
273 tmp2 |= data[1]; tmp2 <<= 8;
274 tmp2 |= data[0];
275 /* get number of lines */
276 tmp = data[5]; tmp <<= 8;
277 tmp |= data[4];
278 printf("\tdumping %d raster data bytes (%d lines):", tmp2, tmp);
279 for (tmp = 0; tmp < tmp2; tmp++) {
280 if ((tmp & 0xf) == 0) printf("\n\t");
281 printf("%02x ", getchar());
282 i++;
283 }
284 printf("\n\n");
285 }
286
readesc(unsigned char * data)287 static int readesc(unsigned char *data)
288 {
289 unsigned char *p = data, lb, ck;
290
291 ck = *p = getchar();
292 if (feof(stdin)) {
293 printf("Reached EOF at %08x.\n", i);
294 return -1;
295 }
296 if (*p++ != 0x1b) {
297 printf("Expected start of a ESC sequence at %08x.\n", i);
298 return -2;
299 }
300 i++;
301 /* cmd byte */
302 ck += *p++ = getchar(); i++;
303 ck += *p = getchar();
304 if (*p != sq++) {
305 /* ESC 0x51 seems to set sequence numbers, also make
306 * concatetnations of print files work */
307 if ((*p != 0) && (data[1] != 0x51)) {
308 printf("Sequence error (is %02x, should be %02x) at %08x.\n",
309 (int) *p, sq - 1, i);
310 return -3;
311 } else {
312 printf("Sequence restarts at %08x.\n", i);
313 sq = *p + 1;
314 }
315 }
316 p++;
317 i++;
318 ck += lb = *p++ = getchar(); i++;
319 *p = getchar();
320 if (*p++ != 0) {
321 printf("Expected zero byte at %08x.\n", i);
322 return -4;
323 }
324 i++;
325 ck += *p = getchar();
326 if (*p++ != (~data[1] & 0xff)) {
327 printf("Command %02x not terminated at %08x.\n", data[1], i);
328 return -5;
329 }
330 i++;
331
332 while (lb--) {
333 ck += *p++ = getchar();
334 i++;
335 }
336
337 *p = getchar();
338 if (*p != ck) {
339 printf("Checksum error at %08x.\n", i);
340 return -6;
341 }
342
343 return data[1];
344 }
345
main()346 int main()
347 {
348 unsigned char data[300];
349 int c;
350
351 while (!feof(stdin)) {
352 c = readesc(data);
353 if (c < 0) return c;
354
355 switch (c) {
356 case 0x50:
357 dump50(data); break;
358 case 0x51:
359 dump51(data); break;
360 case 0x52:
361 dump52(data); break;
362 default:
363 dumpraw(data); break;
364 }
365 }
366
367 return 0;
368 }
369