As mentioned already, this program does not seem to want to create a temporary file called n670u.raw . As mentioned below, one can always create it first, with "touch," but introduction of a small change on line 593 of the file will take care of it, too.
There, it is possible to add to the "open" operation the option O_CREAT and this takes care of the problem. Suitably edited file attached at the end of this note. Theodore Kilgore ---------- Forwarded message ---------- Date: Thu, 31 Jan 2002 19:40:45 -0600 (CST) From: kilg...@khayyam.math.auburn.edu Reply-To: kilg...@banach.math.auburn.edu To: gunther.ma...@t-online.de Cc: sane-de...@mostang.com Subject: Re: [sane-devel] Canon N670U:merlin670-V0.01 developers release This works. I got a scan out of it. Further remarks: 1. apparently I had to rmmod scanner first, or it was unhappy. 2. I had to run the program as root 3. It didn't want somehow to create the temporary file n670u.raw, but after I did touch n670u.raw it went right ahead and did the scan and exited after going the length of an A4 paper. 4. Congratulations. Not bad. Theodore Kilgore > ---------- Forwarded message ---------- > Date: Thu, 31 Jan 2002 23:44:56 +0100 > From: Gunther Mayer <gunther.ma...@t-online.de> > To: sane-de...@mostang.com > Subject: [sane-devel] Canon N670U:merlin670-V0.01 developers release > > Hi, > my hack "merlin670" already scans at 150 dpi color: > http://home.t-online.de/home/gunther.mayer/merlin-V0.01.c > > This is an early release for developers, no fancy features! > You must even twiddle to get it compiled. See comments in the source. > > This is > - based on libusb (no kernel module scanner.o needed). > - standalone wrt SANE > > Regards, Gunther > _______________________________________________ > Sane-devel mailing list > sane-de...@www.mostang.com > http://www.mostang.com/mailman/listinfo/sane-devel > ----------------edited merlin-V0.01.c follows------------------------ /* * Canon N670U Scanner LM9833 merlin test quick'n dirty (c) Gunther Mayer 2002 GNU Public license * * Test program * For developers only !!! * Just get it scanning, pending refinements. INSTALLING and USING: 1) get,compile,install libusb-0.1.4 No need for "scanner.o" kernel module ! 2) mkdir merlin in libusb's directory (so ".." works) 3) cp merlin670.c merlin 4) cc -o merlin670 -lusb -lm merlin670.c adjust libraries as needed 5) ./merlin670 will do a 150 dpi color scan When you press Ctrl-C "n670u.ppm" will be written (else ca. A4 size will be scanned) */ /* CANON USB models (Canon Vendor ID VID=0x04A9): PID model ??? FB320U ??? FB1210U ??? FB630U/636U ??? D2400UF ??? D660U ??? D1230U 2202 FB620U 2206 N650U 2207 N1220U 220B D646U 220D N670U/N676U *** 220E N1240U N-Series: CIS Scanner D-Series: CCD Scanner */ #include <stdio.h> #include "../usb.h" //libusb ! #include "../usbi.h" #include <errno.h> #include <sys/types.h> #include <fcntl.h> #include <math.h> #include <signal.h> #define wr(reg,val) writereg(reg,val) #define wr2(reg,val) {writereg(reg+1,val&0xff); writereg(reg,val>>8);} void init_like_3a(int); usb_dev_handle *u; usb_dev_handle *findscanner(int vendor, int product); int fraw,ctrlc; void raw2ppm(int lines,int pixperline) { int f,j=0,i=0,rr,gg,bb; FILE *o; char r[16384],g[16384],b[16384]; printf("Creating n670u.ppm %dx%d\n",pixperline,lines); f=open("n670u.raw", O_RDONLY); o=fopen("n670u.ppm","w"); fprintf(o,"P6\n%d %d\n255\n",pixperline,lines); while(j<lines) { j++; rr=read(f,r,pixperline); gg=read(f,g,pixperline); bb=read(f,b,pixperline); for(i=0;i<pixperline;i++) fprintf(o,"%c%c%c",r[i],g[i],b[i]); } fclose(o); } int writereg(int reg, int val) { char buf[5]; int i; buf[0]=0; //0=write command buf[1]=reg;// register buf[2]=0; // MSB number of data bytes to write buf[3]=1; // LSB number of data bytes to write buf[4]=val; //int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout); i=usb_bulk_write(u,3, buf, 5, 500 /*msec*/); if(i!=5) { printf(" write reg 0x%02x:0x%02x usb_bulk_write returned %d\n",reg,val,i); exit(1); } } int readreg_n(int reg,int n, char *b) { char buf[5];int i; buf[0]=1; //1=read command buf[1]=reg; // register buf[2]=n>>8; // MSB of data bytes to read buf[3]=n&0xff;// LSB of data bytes to read i=usb_bulk_write(u,3, buf, 4, 500 /*msec*/); if(i!=4) { printf("usb_bulk_write returned %d\n",i); exit(1); } i=usb_bulk_read(u,2, b, n, 500); if(i!=n) { printf("usb_bulk_read returned %d\n",i); exit(1); } return i; } unsigned char readreg(int reg) { char buf[5]; char reply[1]; int i; buf[0]=1; //1=read command buf[1]=reg;// register buf[2]=0; // MSB number buf[3]=1; // LSB number i=usb_bulk_write(u,3, buf, 4, 500 /*msec*/); if(i!=4) { printf("usb_bulk_write returned %d\n",i); exit(1); } i=usb_bulk_read(u,2, reply, 1, 500); if(i!=1) printf("usb_bulk_read returned %d\n",i); return reply[0]; } // read registers from Scanner: void dumpregs() { int i; for(i=0x0;i<0x80;i++) { if((i%16) ==0) printf("\n0x%02x:",i); if((i%8)==0) printf(" "); if(i==0 || i==5 || i==6) // the dataport read returns with "0 Bytes read", of course. printf("XX "); else printf("%02x ",readreg(i)); } printf("\n"); } // datasheet chapter 10.2 void do_softreset() { printf("softreset\n"); writereg(0x18,0x05); writereg(0x07,0); // idle state writereg(0x18,0x18); // disable sampling writereg(0x07,0x20); // trigger reset writereg(0x18,0x05); writereg(0x07,0); //idle } void buttons() { int i=10; printf("reg7=0x%02x , reg2 is 0x%02x\n",readreg(7),readreg(2)); writereg(0x59,0); printf("reg7=0x%02x , reg2 is 0x%02x\n",readreg(7),readreg(2)); writereg(0x5a,0x90); // Defunct beim Schreiben von 0x10 !!! printf("reg7=0x%02x , reg2 is 0x%02x\n",readreg(7),readreg(2)); //writereg(0x5b,0); while(i) { // i--; printf("reg2 is 0x%02x\n",readreg(2)); } } void scan150_ini(void) { wr(0x08,0x06); //mclk //wr(0x08,0x0a); wr(0x09,0x1c); //150dpi wr(0x22,0); //pix start wr(0x23,0x4b); wr(0x24,0x13); // A4 //wr(0x25,0xab); wr(0x25,0xae); // LineDataSize is rounded up to the next even integer 1242 !? //wr(0x24,0xb2); // nogo wr(0x29,0x02); //lamps wr2(0x2c,0x0017); wr2(0x2e,0x11d2); wr2(0x30,0x0017); wr2(0x32,0x10db); wr2(0x34,0x0017); wr2(0x36,0x0c04); wr(0x38,1); wr(0x39,1); wr(0x3a,1); wr(0x3b,1); wr(0x3c,1); wr(0x3d,1); //wr(0x42,0x20); //nono 0x26 notjet wr(0x42,0x21); wr(0x45,0x13); // motor on wr2(0x46,0x01f2); //stepsize wr2(0x48,0x01f2); // FF stepize wr(0x4e,0x2f); wr(0x4f,0x01); wr(0x50,0x3f); wr(0x51,0xfc); // phase difference on pause wr(0x52,0x77); //0x07 from snoop would produce colorstripes at pause wr(0x53,0xc8); wr(0x58,0); // Sensors must be off, else scanning just halts. } // write 4096 bytes to the data port (register 0x06) per color. // The LM9833 will use the 12 most significant bits of // 16bit ADC as index. So we get a 8 Bit output value per color // LM9833 pdf Figure 43 is plain wrong (as it shows 12 bit values // to be written to the dataport) void download_gamma(float gamma) // Gamma=1 for Linear. { char buf[0x14]; int color,i,j,r; double x,y; for(color=0;color<3;color++) { wr(0x03,0x02 + color*4); // Bits 0 and 1:0x02 Bits 2 and 3:color wr(0x04,0x00); wr(0x05,0x00); for(i=0;i<=0xff;i++) { buf[0]=0; //0=write command buf[1]=0x06; /* register*/ buf[2]=0;// MSB number buf[3]=0x10; // LSB number bytes written for(j=0x4;j<0x14;j++) { x=(i*16 + j-4)/4096.0; y=pow(x,1.0/gamma)*256 ; buf[j]=y; //printf("x gam is %f %f %f\n",x,y,gamma); } r=usb_bulk_write(u,3, buf, 0x14, 500 /*msec*/); if(r!=0x14) { printf(" write reg 0x%02x: gamma usb_bulk_write returned %d\n",6,r); exit(1); } } } } void mysigint(int s) { printf("CTRL-C received.\n"); ctrlc=1; } void scan150(void) { int z=0,i=0,k=0; int r,r1,r3,r7,r4c,r4d; char buf[0x2000]; int lastr1,lastr3,lastr7; signal(SIGINT,mysigint); scan150_ini(); //geht jetzt! //scan150_ini_from_register_dump(); // doesnt work printf("Register Dump before scan:"); dumpregs(); /*wr(0x03,0x0a); wr(0x04,0x40); wr(0x05,0x00);*/ r=readreg(0x06); printf("reg6 is 0x%02x\n",r); printf("registercheck before scan:"); { int r1,r3,r7,r4c,r4d; char buf[0x2000]; r1=readreg(0x01); r3=readreg(0x03); r7=readreg(0x07); r4c=readreg(0x4c); r4d=readreg(0x4d); printf("r1=%d r3=0x%02x r7=0x%2x r4c4d=%02x%02x\n",r1,r3,r7,r4c,r4d); } printf("download gamma 2.5...\n"); download_gamma(2.5); //wr(0x4a,5); //skip /*wr(0x58,0); // sensor home OFF wr(0x07,0x00);*/ printf("\nSCAN 150dpi COLOR until CTRL-C or DIN A4\n"); wr(0x07,0x03); // scannnnn while(1) { r1=readreg(0x01); r3=readreg(0x03); r7=readreg(0x07); if(ctrlc==1) break; //if((lastr1!=r1)||(lastr3!=r3)||(lastr7!=r7)) // printf("r1=%d r3=0x%02x r7=0x%2x\n",r1,r3,r7); if(r1>0x02) { r=readreg_n(0x00,0x2000,buf); k=k+0x2000; z=k/1242/3-1; if(z>1650) break; // ca. DINA4 write(fraw,buf,0x2000); close(fraw); fraw=open("n670u.raw", O_RDWR|O_APPEND); //printf("READ=%d ",r); printf("."); fflush(stdout); } lastr3=r3; lastr1=r1; lastr7=r7; } printf("\n"); do_softreset(); raw2ppm(z,1242); init_like_3a(1); } void playlamp() { wr(0x08,0x3f); // warning: psychedelic frequencies wr2(0x2c,0x0017); wr2(0x2e,0x1225); wr2(0x30,0x0017); wr2(0x32,0x1225); wr2(0x34,0x0017); wr2(0x36,0x1225); wr(0x29,0x02); dumpregs(); } void init_like_3a(int early) { int r,i; wr(0x03,0); wr(0x04,0); wr(0x05,0); wr(0x06,0); wr(0x08,0x0a); wr(0x09,0x1a); wr(0x0a,0); wr(0x0b,0x15); wr(0x0c,0x4c); wr(0x0d,0x2f); wr(0x0e,0); wr(0x0f,0); wr(0x10,0); wr(0x11,0x04); wr(0x12,0x05); wr(0x13,0x06); wr(0x14,0x07); wr(0x15,0); wr(0x16,0); wr(0x17,0); wr(0x18,0x05); wr(0x19,0); wr(0x1a,0); wr(0x1b,0x01); wr(0x1c,0); wr(0x1d,0); wr(0x1e,0); wr(0x1f,0x4b); wr(0x20,0x14); wr(0x21,0xad); wr(0x22,0); wr(0x23,0x4b); wr(0x24,0x14); wr(0x25,0x3b); wr(0x26,0x15); wr(0x27,0); // 0x28 reserved wr(0x29,0); wr(0x2a,0); wr(0x2b,0); wr(0x2c,0x03); wr(0x2d,0xff); wr(0x2e,0); wr(0x2f,0x01); wr(0x30,0x03); wr(0x31,0xff); wr(0x32,0); wr(0x33,0x01); wr(0x34,0x03); wr(0x35,0xff); wr(0x36,0); wr(0x37,0x01); wr(0x38,0); wr(0x39,0); wr(0x3a,0); wr(0x3b,0x01); wr(0x3c,0x01); wr(0x3d,0); wr(0x3e,0); wr(0x3f,0); wr(0x40,0x40); wr(0x41,0); wr(0x42,0x20); wr(0x43,0); wr(0x44,0); wr(0x45,0x13); wr(0x46,0x03); wr(0x47,0xe3); wr(0x48,0x01); wr(0x49,0xf2); wr(0x4a,0); wr(0x4b,0); wr(0x4c,0); wr(0x4d,0); wr(0x4e,0x8c); wr(0x4f,0x01); wr(0x50,0); wr(0x51,0xfc); wr(0x52,0x35); wr(0x53,0x94); wr(0x54,0); wr(0x55,0x0f); wr(0x56,0x08); wr(0x57,0x1f); wr(0x58,0x04); wr(0x59,0x44); // 5a 5b wr(0x5c,0x01); wr(0x5d,0); wr(0x5e,0); wr(0x5f,0); wr(0x60,0); wr(0x61,0); wr(0x62,0); wr(0x63,0); wr(0x64,0); wr(0x65,0); wr(0x66,0); wr(0x67,0); wr(0x68,0); wr(0x69,0); wr(0x6a,0); wr(0x6b,0); wr(0x6c,0); wr(0x6d,0); wr(0x6e,0); wr(0x6f,0); wr(0x70,0); wr(0x71,0); wr(0x72,0); wr(0x73,0); wr(0x74,0); wr(0x75,0); wr(0x76,0); wr(0x77,0); wr(0x78,0); wr(0x79,0); wr(0x7a,0); wr(0x7b,0); wr(0x7c,0); wr(0x7d,0); wr(0x7e,0); wr(0x7f,0); // 5a 5b wr(0x5a,0x94); wr(0x5b,0x19); /* wr(0x07,0); // URB 127 { int r18; r18=readreg(0x18); wr(0x18,0x18); wr(0x07,0x20); wr(0x18,r18); //0x05 wr(0x07,0x00); wr(0x07,0x00); } */ wr(0x5b,0x11); // URB 140 wr(0x5b,0x91); r=readreg(0x5a); wr(0x5a,0x14); r=readreg(0x09); wr(0x09,r); wr(0x5a,0x16); //URB 151 ERR-1 wr(0x59,0x66); // URB 152 wr(0x70,0x73); // URB 406 wr(0x2c,0x3f); //URB 473 LAMP off wr(0x30,0x3f); wr(0x34,0x3f); //playlamp(); exit(1); //wr(0x48,0x01); // fast feed step size wr(0x48,0x00); wr(0x49,0xf2); wr(0x57,0x3f); // //URB 421 pwm //wr(0x57,0x1f); //wr(0x58,0);// XXXXXXXXXX r=readreg(0x02); printf("r2 is 0x%02x\n",r); if(r==0) {printf("r is null.exit\n");exit(1);} if(!(r&1)) {// not at home position printf("Homing sensor...\n"); wr(0x07,02); while(1) { static int lastr=2000; int r7,r2; r2=readreg(0x02); r7=readreg(0x07); if(lastr!=r7) printf("r2=0x%02x, r7=%02x\n",r2,r7); lastr=r7; if(r7!=2) break; } } if(early) return; wr(0x4a,0x2); printf("Sensor prog FORW\n"); wr(0x07,0x05); while(1) { static int lastr=2000; int r2,r7; r2=readreg(0x02); r7=readreg(0x07); if(lastr!=r7) printf("r2=0x%02x, r7=%02x\n",r2,r7); lastr=r7; if(r7!=5) break; } wr(0x07,0x02); // REVERSE until HOME i=10; while(1) { int r2,r7; static int lastr=2000; r2=readreg(0x02); r7=readreg(0x07); if(lastr!=r) printf("r2=0x%02x, r7=%02x\n",r2,r7); lastr=r; if(r7!=2) break; } return; wr(0x57,0x33); //URB 570 wr(0x07,0x01); //FORWARD 2581ms wr(0x51,0x00); // accel profile // wait for reg02 go from 63->62 while(1) { int r; r=readreg(0x02); printf("r2 is 0x%02x ",r); if(r!=0x63) break; } wr(0x07,0x00); // STOP } int main(void) { int i=0,r=0; printf("Merlin670 V0.01 for developers only\n"); u=findscanner(0x04a9 /*canon*/ ,0x220d /* N670U/N676U*/); if(u==NULL) {printf("scanner not found. exiting.\n"); return 1;} //printf("found u=%p\n",u); //printf("Bus/Device= %p/%p, config=%d interface=%d altsetting=%d\n", // u->bus, u->device, u->config, u->interface, u->altsetting); i=usb_claim_interface(u,0); printf("usb_claim_interface returned %d\n",i); if(i!=0) { printf("could not claim scanner)! exiting.\n"); exit(1);} i=usb_set_configuration(u,1); printf("usb_set_configuration returned %d\n",i); if(i!=0) exit(1); writereg(7,0); printf("Initial Register Dump",i,r); dumpregs(); fraw=open("n670u.raw",O_CREAT|O_TRUNC|O_RDWR); if(fraw==-1) {printf("couldn open n670u.raw, errno=%d\n",errno); exit(1);} init_like_3a(0); scan150(); //buttons(); exit(1); return 0; } usb_dev_handle *findscanner(int vendor, int product) { struct usb_bus *bus; struct usb_device *dev; usb_init(); usb_find_busses(); usb_find_devices(); printf("Searching USB for CanoScan N670U/N676U VID=%04x PID=%04x\n",vendor,product); printf("bus/device idVendor/idProduct\n"); for (bus = usb_busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { printf("%s/%s %04X/%04X\n", bus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct); if((dev->descriptor.idVendor==vendor)&& (dev->descriptor.idProduct==product)) return usb_open(dev); } } return NULL; }