This source file includes following definitions.
- mustek_attach
- mustek_set_params
- mustek_minphys
- mustek_trigger_scanner
- mustek_rewind_scanner
- mustek_read
- mustek_get_status
- mustek_compute_sizes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <sys/kernel.h>
52 #include <sys/systm.h>
53 #include <sys/fcntl.h>
54 #include <sys/errno.h>
55 #include <sys/ioctl.h>
56 #include <sys/malloc.h>
57 #include <sys/buf.h>
58 #include <sys/proc.h>
59 #include <sys/user.h>
60 #include <sys/device.h>
61 #include <sys/conf.h>
62 #include <sys/scanio.h>
63
64 #include <scsi/scsi_all.h>
65 #include <scsi/scsi_scanner.h>
66 #include <scsi/scsiconf.h>
67 #include <scsi/ssvar.h>
68 #include <scsi/ss_mustek.h>
69
70 #define MUSTEK_RETRIES 4
71
72 int mustek_set_params(struct ss_softc *, struct scan_io *);
73 int mustek_trigger_scanner(struct ss_softc *);
74 void mustek_minphys(struct ss_softc *, struct buf *);
75 int mustek_read(struct ss_softc *, struct buf *);
76 int mustek_rewind_scanner(struct ss_softc *);
77
78
79 int mustek_get_status(struct ss_softc *, int, int);
80 void mustek_compute_sizes(struct ss_softc *);
81
82
83
84
85 struct ss_special mustek_special = {
86 mustek_set_params,
87 mustek_trigger_scanner,
88 NULL,
89 mustek_minphys,
90 mustek_read,
91 mustek_rewind_scanner,
92 NULL,
93 NULL
94 };
95
96
97
98
99 void
100 mustek_attach(ss, sa)
101 struct ss_softc *ss;
102 struct scsi_attach_args *sa;
103 {
104 #ifdef SCSIDEBUG
105 struct scsi_link *sc_link = sa->sa_sc_link;
106 #endif
107
108 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_attach: start\n"));
109 ss->sio.scan_scanner_type = 0;
110
111 printf("\n%s: ", ss->sc_dev.dv_xname);
112
113
114 if (!bcmp(sa->sa_inqbuf->product, "MFS-06000CX", 11)) {
115 ss->sio.scan_scanner_type = MUSTEK_06000CX;
116 printf("Mustek 6000CX Flatbed 3-pass color scanner, 3 - 600 dpi\n");
117 }
118 if (!bcmp(sa->sa_inqbuf->product, "MFS-12000CX", 11)) {
119 ss->sio.scan_scanner_type = MUSTEK_12000CX;
120 printf("Mustek 12000CX Flatbed 3-pass color scanner, 6 - 1200 dpi\n");
121 }
122
123 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_attach: scanner_type = %d\n",
124 ss->sio.scan_scanner_type));
125
126
127 ss->special = mustek_special;
128
129 mustek_compute_sizes(ss);
130 }
131
132
133
134
135
136
137 int
138 mustek_set_params(ss, sio)
139 struct ss_softc *ss;
140 struct scan_io *sio;
141 {
142 int error;
143
144
145
146
147 if (ss->flags & SSF_TRIGGERED) {
148 error = mustek_rewind_scanner(ss);
149 if (error)
150 return (error);
151 }
152
153
154 #ifdef MUSTEK_INCH_SPEC
155
156 sio->scan_x_origin -= sio->scan_x_origin % 150;
157 sio->scan_y_origin -= sio->scan_y_origin % 150;
158 sio->scan_width -= sio->scan_width % 150;
159 sio->scan_height -= sio->scan_height % 150;
160 #endif
161 if (sio->scan_width == 0 ||
162 sio->scan_x_origin + sio->scan_width > 10200 ||
163 sio->scan_height == 0 ||
164 sio->scan_y_origin + sio->scan_height > 16800)
165 return (EINVAL);
166
167
168
169
170
171
172
173
174
175
176 sio->scan_x_resolution -= sio->scan_x_resolution <= 300 ?
177 sio->scan_x_resolution % 3 : sio->scan_x_resolution % 30;
178 sio->scan_y_resolution -= sio->scan_y_resolution <= 300 ?
179 sio->scan_y_resolution % 3 : sio->scan_y_resolution % 30;
180 if (sio->scan_x_resolution < 3 || sio->scan_x_resolution > 600 ||
181 sio->scan_x_resolution != sio->scan_y_resolution)
182 return (EINVAL);
183
184
185 sio->scan_brightness -= (sio->scan_brightness - 64) % 3;
186 if (sio->scan_brightness < 64 || sio->scan_brightness > 136)
187 return (EINVAL);
188
189
190 sio->scan_contrast -= (sio->scan_contrast - 16) % 7;
191 if (sio->scan_contrast < 16 || sio->scan_contrast > 184)
192 return (EINVAL);
193
194
195
196
197
198
199 sio->scan_quality -= sio->scan_quality % 20;
200 if (sio->scan_quality < 20 || sio->scan_quality > 100)
201 return (EINVAL);
202
203 switch (sio->scan_image_mode) {
204 case SIM_BINARY_MONOCHROME:
205 case SIM_DITHERED_MONOCHROME:
206 case SIM_GRAYSCALE:
207 case SIM_RED:
208 case SIM_GREEN:
209 case SIM_BLUE:
210 break;
211 default:
212 return (EINVAL);
213 }
214
215
216 sio->scan_scanner_type = ss->sio.scan_scanner_type;
217 bcopy(sio, &ss->sio, sizeof(struct scan_io));
218
219 mustek_compute_sizes(ss);
220
221 return (0);
222 }
223
224
225
226
227
228
229
230
231 void
232 mustek_minphys(ss, bp)
233 struct ss_softc *ss;
234 struct buf *bp;
235 {
236 #ifdef SCSIDEBUG
237 struct scsi_link *sc_link = ss->sc_link;
238 #endif
239
240 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_minphys: before: %ld\n",
241 bp->b_bcount));
242 bp->b_bcount -= bp->b_bcount %
243 ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8);
244 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_minphys: after: %ld\n",
245 bp->b_bcount));
246 }
247
248
249
250
251
252
253 int
254 mustek_trigger_scanner(ss)
255 struct ss_softc *ss;
256 {
257 struct mustek_mode_select_cmd mode_cmd;
258 struct mustek_mode_select_data mode_data;
259 struct mustek_set_window_cmd window_cmd;
260 struct mustek_set_window_data window_data;
261 struct mustek_start_scan_cmd start_scan_cmd;
262 struct scsi_link *sc_link = ss->sc_link;
263 int pixel_tlx, pixel_tly, pixel_brx, pixel_bry, paperlength;
264 int error;
265
266 mustek_compute_sizes(ss);
267
268 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner\n"));
269
270
271
272
273 bzero(&window_cmd, sizeof(window_cmd));
274 window_cmd.opcode = MUSTEK_SET_WINDOW;
275 window_cmd.length = sizeof(window_data);
276
277 bzero(&window_data, sizeof(window_data));
278 window_data.frame.header = MUSTEK_LINEART_BACKGROUND | MUSTEK_UNIT_SPEC;
279 #ifdef MUSTEK_INCH_SPEC
280
281 pixel_tlx = ss->sio.scan_x_origin / 150;
282 pixel_tly = ss->sio.scan_y_origin / 150;
283 pixel_brx = pixel_tlx + ss->sio.scan_width / 150;
284 pixel_bry = pixel_tly + ss->sio.scan_height / 150;
285 #else
286 pixel_tlx = (ss->sio.scan_x_origin * ss->sio.scan_x_resolution) / 1200;
287 pixel_tly = (ss->sio.scan_y_origin * ss->sio.scan_y_resolution) / 1200;
288 pixel_brx = pixel_tlx +
289 (ss->sio.scan_width * ss->sio.scan_x_resolution) / 1200;
290 pixel_bry = pixel_tly +
291 (ss->sio.scan_height * ss->sio.scan_y_resolution) / 1200;
292 #endif
293 _lto2l(pixel_tlx, window_data.frame.tl_x);
294 _lto2l(pixel_tly, window_data.frame.tl_y);
295 _lto2l(pixel_brx, window_data.frame.br_x);
296 _lto2l(pixel_bry, window_data.frame.br_y);
297
298 #if MUSTEK_WINDOWS >= 1
299 window_data.window1 = window_data.frame;
300 window_data.window1.header = MUSTEK_WINDOW_MASK | MUSTEK_UNIT_SPEC;
301 #endif
302
303
304 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_set_parms: set_window\n"));
305 error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &window_cmd,
306 sizeof(window_cmd), (u_char *) &window_data, sizeof(window_data),
307 MUSTEK_RETRIES, 5000, NULL, SCSI_DATA_OUT);
308 if (error)
309 return (error);
310
311
312
313
314 bzero(&mode_cmd, sizeof(mode_cmd));
315 mode_cmd.opcode = MUSTEK_MODE_SELECT;
316 _lto2b(sizeof(mode_data), mode_cmd.length);
317
318 bzero(&mode_data, sizeof(mode_data));
319 mode_data.mode =
320 MUSTEK_MODE_MASK | MUSTEK_HT_PATTERN_BUILTIN | MUSTEK_UNIT_SPEC;
321 if (ss->sio.scan_x_resolution <= 300) {
322 mode_data.resolution = ss->sio.scan_x_resolution / 3;
323 } else {
324
325
326
327
328 mode_data.resolution =
329 ((ss->sio.scan_x_resolution - 1) % 100) + 1;
330 }
331 mode_data.brightness = (ss->sio.scan_brightness - 64) / 3;
332 mode_data.contrast = (ss->sio.scan_contrast - 16) / 7;
333 mode_data.grain = 0;
334 mode_data.velocity = ss->sio.scan_quality / 20 - 1;
335 #ifdef MUSTEK_INCH_SPEC
336 paperlength = 14 * 8;
337 #else
338 paperlength = 14 * ss->sio.scan_y_resolution;
339 #endif
340 _lto2l(paperlength, mode_data.paperlength);
341
342 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner: mode_select\n"));
343
344 error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &mode_cmd,
345 sizeof(mode_cmd), (u_char *) &mode_data, sizeof(mode_data),
346 MUSTEK_RETRIES, 5000, NULL, SCSI_DATA_OUT);
347 if (error)
348 return (error);
349
350
351
352
353 bzero(&start_scan_cmd,sizeof(start_scan_cmd));
354 start_scan_cmd.opcode = MUSTEK_START_STOP;
355 start_scan_cmd.mode = MUSTEK_SCAN_START;
356 if (ss->sio.scan_x_resolution <= 300)
357 start_scan_cmd.mode |= MUSTEK_RES_STEP_1;
358 else
359 start_scan_cmd.mode |= MUSTEK_RES_STEP_10;
360 switch (ss->sio.scan_image_mode) {
361 case SIM_BINARY_MONOCHROME:
362 case SIM_DITHERED_MONOCHROME:
363 start_scan_cmd.mode |= MUSTEK_BIT_MODE | MUSTEK_GRAY_FILTER;
364 break;
365 case SIM_GRAYSCALE:
366 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_GRAY_FILTER;
367 break;
368 case SIM_RED:
369 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_RED_FILTER;
370 break;
371 case SIM_GREEN:
372 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_GREEN_FILTER;
373 break;
374 case SIM_BLUE:
375 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_BLUE_FILTER;
376 break;
377 }
378
379
380 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner: start_scan\n"));
381 error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &start_scan_cmd,
382 sizeof(start_scan_cmd), NULL, 0,
383 MUSTEK_RETRIES, 5000, NULL, 0);
384 if (error)
385 return (error);
386
387
388
389
390
391
392
393 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner: get_status\n"));
394 error = mustek_get_status(ss, 60, 1);
395 if (error)
396 return (error);
397
398 return (0);
399 }
400
401
402
403
404 int
405 mustek_rewind_scanner(ss)
406 struct ss_softc *ss;
407 {
408 struct mustek_start_scan_cmd cmd;
409 struct scsi_link *sc_link = ss->sc_link;
410 int error;
411
412 if (ss->sio.scan_window_size != 0) {
413
414
415
416
417 bzero(&cmd, sizeof(cmd));
418 cmd.opcode = MUSTEK_START_STOP;
419 cmd.mode = MUSTEK_SCAN_STOP;
420
421
422 SC_DEBUG(sc_link, SDEV_DB1,
423 ("mustek_rewind_scanner: stop_scan\n"));
424 error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
425 sizeof(cmd), NULL, 0, MUSTEK_RETRIES, 5000, NULL, 0);
426 if (error)
427 return (error);
428 }
429
430 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_rewind_scanner: end\n"));
431
432 return (0);
433 }
434
435
436
437
438 int
439 mustek_read(ss, bp)
440 struct ss_softc *ss;
441 struct buf *bp;
442 {
443 struct mustek_read_cmd cmd;
444 struct scsi_link *sc_link = ss->sc_link;
445 u_long lines_to_read;
446
447 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_read: start\n"));
448
449 bzero(&cmd, sizeof(cmd));
450 cmd.opcode = MUSTEK_READ;
451
452
453 lines_to_read = bp->b_bcount /
454 ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8);
455 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_read: read %ld lines\n",
456 lines_to_read));
457 _lto3b(lines_to_read, cmd.length);
458
459
460
461
462 if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, sizeof(cmd),
463 (u_char *) bp->b_data, bp->b_bcount, MUSTEK_RETRIES, 10000, bp,
464 SCSI_NOSLEEP | SCSI_DATA_IN) != SUCCESSFULLY_QUEUED)
465 printf("%s: not queued\n", ss->sc_dev.dv_xname);
466 else {
467 ss->sio.scan_lines -= lines_to_read;
468 ss->sio.scan_window_size -= bp->b_bcount;
469 }
470
471 return (0);
472 }
473
474
475
476
477
478
479
480
481 int
482 mustek_get_status(ss, timeout, update)
483 struct ss_softc *ss;
484 int timeout, update;
485 {
486 struct mustek_get_status_cmd cmd;
487 struct mustek_get_status_data data;
488 struct scsi_link *sc_link = ss->sc_link;
489 int error, lines, bytes_per_line;
490
491 bzero(&cmd, sizeof(cmd));
492 cmd.opcode = MUSTEK_GET_STATUS;
493 cmd.length = sizeof(data);
494
495 while (1) {
496 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_get_status: stat_cmd\n"));
497 error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
498 sizeof(cmd), (u_char *) &data, sizeof(data), MUSTEK_RETRIES,
499 5000, NULL, SCSI_DATA_IN);
500 if (error)
501 return (error);
502 if ((data.ready_busy == MUSTEK_READY) ||
503 (timeout-- <= 0))
504 break;
505
506 tsleep((caddr_t)mustek_get_status, PRIBIO + 1, "mtkrdy", hz);
507 }
508
509 if (update) {
510 bytes_per_line = _2ltol(data.bytes_per_line);
511 lines = _3ltol(data.lines);
512 if (lines != ss->sio.scan_lines) {
513 printf("mustek: lines actual(%d) != computed(%ld)\n",
514 lines, ss->sio.scan_lines);
515 return (EIO);
516 }
517 if (bytes_per_line * lines != ss->sio.scan_window_size) {
518 printf("mustek: win-size actual(%d) != computed(%ld)\n",
519 bytes_per_line * lines, ss->sio.scan_window_size);
520 return (EIO);
521 }
522
523 SC_DEBUG(sc_link, SDEV_DB1,
524 ("mustek_get_size: bpl=%ld, lines=%ld\n",
525 (ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8,
526 ss->sio.scan_lines));
527 SC_DEBUG(sc_link, SDEV_DB1, ("window size = %ld\n",
528 ss->sio.scan_window_size));
529 }
530
531 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_get_status: end\n"));
532 if (data.ready_busy == MUSTEK_READY)
533 return (0);
534 else
535 return (EBUSY);
536 }
537
538
539
540
541
542 void
543 mustek_compute_sizes(ss)
544 struct ss_softc *ss;
545 {
546
547 switch (ss->sio.scan_image_mode) {
548 case SIM_BINARY_MONOCHROME:
549 case SIM_DITHERED_MONOCHROME:
550 ss->sio.scan_bits_per_pixel = 1;
551 break;
552 case SIM_GRAYSCALE:
553 case SIM_RED:
554 case SIM_GREEN:
555 case SIM_BLUE:
556 ss->sio.scan_bits_per_pixel = 8;
557 break;
558 }
559
560
561
562
563
564 ss->sio.scan_pixels_per_line =
565 (ss->sio.scan_width * ss->sio.scan_x_resolution) / 1200;
566 if (ss->sio.scan_bits_per_pixel == 1)
567
568 ss->sio.scan_pixels_per_line =
569 (ss->sio.scan_pixels_per_line + 15) & 0xfffffff0;
570 else
571 ss->sio.scan_pixels_per_line =
572 (ss->sio.scan_pixels_per_line + 1) & 0xfffffffe;
573
574 ss->sio.scan_lines =
575 (ss->sio.scan_height * ss->sio.scan_y_resolution) / 1200;
576 ss->sio.scan_window_size = ss->sio.scan_lines *
577 ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8);
578 }