add support for ricoh aficio sp100su

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
this printer/scanner model is not supported, so i give you the informations i have about it
and my tests after compiling latest version of backends

lsusb gives :
Bus 002 Device 111: ID 05ca:042c Ricoh Co., Ltd

sudo sane find scanner gives :
found USB scanner (vendor=0x05ca [RICOH], product=0x042c [Aficio SP 100SU]) at libusb:002:111

added in 40-libsane
ATTRS{idVendor}=="05ca", ATTRS{idProduct}=="042c", ENV{libsane_matched}="yes"

also tryed with
ATTRS{idVendor}=="05ca", ATTRS{idProduct}=="042c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes"

ricoh.conf content is :
usb 0x05ca 0x042c

also tryed with [usb] 0x05ca 0x042c
tryed to add device auto
tryed to add device /dev/usbscanner

scanimage -L gives
no sane device detected

scanimage -d ricoh:libusb:002:111 gives
scanimage: open of device ricoh:libusb:002:111 failed: Invalid argument

after unmounted the printer im able to give you the chip list
winbond w9812g6jh-6 1326w 63015m800
ia le-2 1ax00105s1996 1230 php8y700b cn
amm56219 070819 l/f asts1328ac
r4f24255vfpu n8s/2425 n 1338 aj02112
all that on a ua1310 version 2.0 mainboard
additionnal post-it show m1025005m 313100efd 2e tk9021441588d (1310)

firmware/drivers are here
http://support.ricoh.com/bb/html/dr_ut_e/apc/model/sp_100su/sp_100su.htm?lang=en

the back of the printer
sp100su e
serial t283mb73338
code m102-27
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
after some investigation i found i was able to do that
but my knowelge about usb commincation is zero
i will need some help to continue to investigate this printer

satellite@satellite-Satellite-P200-1BY:~$ sudo python
>>> import usb
>>> dev = usb.core.find(idVendor=0x05ca, idProduct=0x042c)
>>> print dev
DEVICE ID 05ca:042c on Bus 002 Address 119 =================
 bLength                :   0x12 (18 bytes)
 bDescriptorType        :    0x1 Device
 bcdUSB                 :  0x200 USB 2.0
 bDeviceClass           :    0x0 Specified at interface
 bDeviceSubClass        :    0x0
 bDeviceProtocol        :    0x0
 bMaxPacketSize0        :   0x40 (64 bytes)
 idVendor               : 0x05ca
 idProduct              : 0x042c
 bcdDevice              :  0x100 Device 1.0
 iManufacturer          :    0x1 RICOH
 iProduct               :    0x2 Aficio SP 100SU
 iSerialNumber          :    0x3 T283MB73338
 bNumConfigurations     :    0x1
  CONFIGURATION 1: 2 mA ====================================
   bLength              :    0x9 (9 bytes)
   bDescriptorType      :    0x2 Configuration
   wTotalLength         :   0x3e (62 bytes)
   bNumInterfaces       :    0x2
   bConfigurationValue  :    0x1
   iConfiguration       :    0x0
   bmAttributes         :   0xc0 Self Powered
   bMaxPower            :    0x1 (2 mA)
    INTERFACE 0: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x3
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :   0xff
     iInterface         :    0x0
      ENDPOINT 0x3: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x3 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x0
      ENDPOINT 0x84: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x84 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x0
      ENDPOINT 0x85: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x85 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x0
    INTERFACE 1: Printer ===================================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x2
     bInterfaceClass    :    0x7 Printer
     bInterfaceSubClass :    0x1
     bInterfaceProtocol :    0x2
     iInterface         :    0x0
      ENDPOINT 0x1: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x1 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x0
      ENDPOINT 0x82: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x82 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x0
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
In reply to this post by viruxx
i dunno if its good, but i tested this:
enabled all in dll.conf
added "device auto" in all .conf file

here's the new result of scanimage -L

[gphoto2] init_gphoto2: error: serial:/dev/ttyd1 is not a valid gphoto2 port.  Use "gphoto2 --list-ports" for list.
[epsonds] unable to parse config line: device auto
device `test:0' is a Noname frontend-tester virtual device
device `test:1' is a Noname frontend-tester virtual device
device `pnm:0' is a Noname PNM file reader virtual device
device `pnm:1' is a Noname PNM file reader virtual device
device `hp3900:device auto' is a Unknown RTS8822 chipset based flatbed scanner
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
In reply to this post by viruxx
my current experimentation is usb sniffing under windows xp during a color a4 scan preview

i try to report the values i found in linux py2usb and read the scanner response

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)3
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)3
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x03\x05\xFF\x00\x00\x00\x00\xE8\x13\x68\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 180, 13, 244, 9, 180, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x18\x9B\x01\x01"); //scanner motor start to do the noise he do before a scan // the light do a fast on/off // the lcd screen say pc capturing

//if wait 60s he do the end scan noise (charret back to idle pos)
//note : communication is busy, cancel button does nothing

//the windows computer is sending 2 sequences here, the first who make the motor doing noise, and the second, i believe is for start the scan but i got a timeout error

here is the full sequence i dont arrive to achieve

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x18\x9B\x01\x01\x00\x00\x00\xE8\x13\x68\x1B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\x0F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); dev.read(0x85,100)
<<<usb.core.USBError: [Errno 110] Operation timed out

my knowledge is zero in this domain, so im lost in this error. i will now do some other tests of this start sequence with other option, b/w, grayscale, resolution changing
will post it here in a few moment
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
In reply to this post by viruxx
here is the grayscale a4 preview (same than b/w a4 preview)

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x02\x05\xFF\x00\x00\x00\x00\xE8\x13\x68\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 180, 13, 244, 9, 180, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x08\x89\x00\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xFA"); dev.read(0x85,100) //error

__________________________________________________________________________
here is the color full size normal scan

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x03\x05\xFF\x00\x00\x00\x00\xEC\x13\x6c\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 182, 13, 246, 9, 182, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x54\x9B\x01\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xF0"); dev.read(0x85,100) //error

________________________________________________________

here is the color trim/clip normal scan

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x03\x05\xFF\x00\x00\x00\x00\x80\x0a\x80\x0E");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 6, 64, 7, 64, 5, 64, 7]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x80\x82\x00\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xFC"); dev.read(0x85,100) //error

_________________________________________________________________

here is the grayscale full size normal scan

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x02\x05\xFF\x00\x00\x00\x00\xEC\x13\x6C\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 182, 13, 246, 9, 182, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x1C\x89\x00\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xFA"); dev.read(0x85,100) //error

_______________________________________________________

here is the grayscale trim/clip scan

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x02\x05\xFF\x00\x00\x00\x00\x1C\x0A\xB4\x0D");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 6, 218, 6, 14, 5, 218, 6]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x1C\x29\x00\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xFC"); dev.read(0x85,100) //error

_________________________________________________________

here is the color a4 preview with luminosity reduced at minimum

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x03\x05\xFF\x00\x00\x00\x00\xE8\x13\x68\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 180, 13, 244, 9, 180, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x18\x9B\x01\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xF0"); dev.read(0x85,100) //error

_________________________________________________________

here is the color a4 preview with luminosity pushed at maximum

 same, so i think its software controled

_________________________________________________________

here is the color a4 normal scan 150pp with luminosity reduced at minimum

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x03\x05\xFF\x00\x00\x00\x00\xEC\x13\x6C\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 182, 13, 246, 9, 182, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x54\x9B\x01\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xF0"); dev.read(0x85,100) //error

_________________________________________________________

here is the color a4 normal scan 150pp with luminosity pushed at maximum

same

_________________________________________________________

here is the color a4 normal scan 600pp

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x02\x03\x05\xFF\x00\x00\x00\x00\xEC\x13\x6C\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 20, 108, 27, 236, 19, 108, 27]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x50\x6D\x06\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xF0"); dev.read(0x85,100) //error

_________________________________________________________

here is the grayscale a4 normal scan 600pp

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x02\x02\x05\xFF\x00\x00\x00\x00\xEC\x13\x6C\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 20, 108, 27, 136, 19, 108, 27]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x70\x24\x02\x01"); //scanner noise
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xF0"); dev.read(0x85,100) //error
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
In reply to this post by viruxx
after take a better look in the windows xp sniffer, it seems that the last sequence who give me a timeout error is a repeating "data received completed" after scanner send multiple sequences of 61440 bytes

<<< array of raw data 61440 bytes
>>> 03 0e 04 00 00 00 00 f0
<<< array of raw data 61440 bytes
>>> 03 0e 04 00 00 00 00 f0
<<< array of raw data 61440 bytes
>>> 03 0e 04 00 00 00 00 f0
and so on

i dont understand why i m not able to do the same in py2usb
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
ok finally im able to do the full scan procedure manually

import usb
dev = usb.core.find(idVendor=0x05ca, idProduct=0x0042c)

dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100);
dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100);
dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x02\x02\x05\xFF\x00\x00\x00\x00\xEC\x13\x6C\x1B"); dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100);
dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x70\x24\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
while true:
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
 dev.read(0x85,61440);



_____________________________________________________
a part of the result


[...]117, 118, 116, 117, 114, 116, 116, 116, 116, 110, 117, 117, 119, 115, 114, 117, 114, 116, 113, 116, 117, 116, 118, 118, 116, 119, 115, 118, 116, 116, 115, 114, 115, 114, 116, 116, 113, 114, 114, 113, 117, 116, 115, 116, 113, 114, 114, 115, 115, 114, 116, 111, 117, 114, 113, 116, 114, 115, 114, 112, 116, 117, 117, 115, 113, 117, 111, 114, 115, 112, 112, 110, 115, 114, 114, 114, 112, 114, 115, 114, 115, 116, 113, 114, 115, 115, 115, 113, 113, 111, 111, 114, 116, 114, 110, 109, 114, 115, 114, 113, 112, 113, 111, 109, 111, 114, 113, 114, 112, 110, 116, 112, 115, 111, 111, 119, 112, 109, 114, 113, 114, 110, 111, 113, 110, 114, 114, 113, 110, 111, 115, 111, 115, 114, 112, 114, 112, 113, 111, 109, 114, 113, 111, 114, 108, 107, 110, 113, 106, 110, 115, 112, 113, 115, 117, 120, 110, 110, 111, 111, 108, 107, 109, 113, 111, 106, 110, 106, 111, 108, 111, 111, 110, 111, 107, 108, 110, 111, 107, 106, 113, 108, 107, 108, 107, 108, 107, 110, 111, 107, 110, 109, 111, 110, 109, 108, 110, 114, 110, 105, 111, 109, 106, 108, 107, 108, 104, 107, 110, 110, 106, 106, 113, 107, 106, 111, 105, 112, 108, 109, 108, 109, 107, 105, 104, 107, 106, 105, 105, 105, 107, 105, 105, 106, 107, 103, 105, 105, 103, 105, 103, 101, 106, 103, 102, 110, 110, 107, 105, 105, 108, 110, 106, 106, 105, 106, 108, 102, 102, 99, 105, 104, 106, 94, 104, 108, 98, 104, 104, 103, 102, 102, 104, 101, 100, 105, 108, 106, 105, 105, 111, 103, 106, 106, 105, 103, 103, 102, 102, 105, 108, 100, 102, 107, 98, 105, 103, 102, 105, 98, 102, 102, 103, 104, 102, 105, 97, 100, 104, 98, 102, 100, 107, 104, 96, 105, 101, 101, 103, 101, 105, 102, 101, 103, 98, 102, 101, 102, 102, 101, 104, 101, 103, 103, 104, 101, 101, 103, 98, 101, 101, 97, 102, 94, 101, 101, 103, 102, 102, 101, 101, 102, 100, 101, 103, 99, 95, 101, 103, 100, 99, 104, 101, 100, 100, 103, 104, 99, 94, 97, 103, 104, 104, 101, 100, 107, 101, 99, 100, 97, 102, 104, 105, 105, 98, 100, 102, 103, 102, 103, 99, 99, 102, 98, 104, 99, 102, 107, 104, 98, 103, 100, 103, 100, 98, 94, 97, 102, 102, 98, 104, 92, 100, 100, 95, 96, 97, 100, 101, 104, 96, 101, 105, 101, 99, 102, 102, 98, 103, 97, 101, 104, 100, 104, 99, 105, 101, 99, 98, 100, 102, 99, 102, 98, 94, 105, 104, 108, 103, 103, 102, 98, 102, 100, 98, 106, 99, 96, 103, 96, 102, 95, 100, 100, 95, 100, 95, 102, 96, 94, 101, 97, 97, 100, 96, 98, 91, 96, 100, 98, 102, 97, 94, 95, 96, 99, 95, 95, 101, 93, 92, 99, 101, 99, 100, 94, 95, 100, 89, 95, 99, 91, 93, 98, 95, 91, 95, 98, 97, 93, 99, 101, 93, 87, 93, 96, 100, 97, 100, 100, 99, 95, 99, 99, 89, 101, 86, 94, 89, 87, 101, 86, 100, 93, 92, 95, 99, 96, 100, 94, 91, 89, 91, 98, 96, 97, 88, 97, 93, 90, 94, 96, 98, 89, 85, 98, 94, 92, 96, 88, 96, 87, 93, 95, 90, 95, 95, 94, 89, 84, 100, 92, 87, 89, 95, 91, 92, 91, 92, 90, 96, 83, 96, 97, 89, 95, 93, 97, 96, 83, 91, 91, 93, 87, 92, 83, 88, 93, 93, 91, 95, 84, 101, 90, 75, 91, 87, 86, 87, 88, 87, 91, 87, 85, 86, 96, 91, 88, 92, 87, 94, 85, 90, 91, 87, 85, 90, 91, 75, 81, 92, 88, 89, 85, 92, 85, 83, 95, 59, 87, 99, 76, 93, 76, 88, 87, 82, 93, 88, 91, 96, 79, 92, 92, 75, 93, 88, 91, 88, 83, 95, 87, 84, 94, 82, 88, 87, 88, 85, 71, 80, 85, 85, 89, 88, 89, 86, 83, 93, 75, 88, 87, 81, 90, 84, 84, 81, 81, 79, 81, 88, 88, 87, 77, 70, 89, 82, 78, 90, 83, 86, 88, 87, 89, 87, 92, 80, 72, 86, 77, 86, 84, 84, 84, 74, 94, 88, 79, 88, 81, 87, 78, 87, 87, 75, 90, 81, 88, 81, 78, 85, 85, 86, 85, 83, 84, 88, 88, 82, 84, 86, 71, 74, 86, 65, 98, 80, 88, 88, 76, 69, 78, 84, 78, 73, 79, 86, 77, 92, 75, 88, 77, 80, 81, 73, 84, 71, 79, 91, 79, 83, 79, 85, 83, 83, 88, 81, 75, 72, 78, 87, 78, 79, 90, 76, 88, 81, 70, 58, 84, 76, 84, 80, 84, 75, 86, 80, 69, 86, 72, 75, 86, 81, 84, 80, 83, 81, 85, 82, 70, 83, 83, 92, 89, 63, 80, 82, 80, 75, 77, 87, 80, 74, 70, 71, 90, 81, 84, 78, 62, 67, 75, 77, 71, 80, 72, 75, 72, 87, 72, 81, 71, 83, 77, 67, 78, 70, 70, 73, 65, 82, 77, 93, 57, 65, 89, 73, 83, 75, 70, 77, 69, 74, 79, 63, 78, 74, 69, 64, 78, 82, 65, 82, 66, 63, 79, 74, 65, 78, 63, 84, 69, 70, 70, 51, 79, 67, 85, 76, 59, 88, 64, 71, 67, 58, 80, 63, 80, 77, 71, 73, 62, 62, 77, 68, 70, 83, 61, 68, 65, 75, 64, 63, 71, 71, 79, 76, 62, 71, 65, 61, 65, 69, 65, 52, 70, 62, 55, 65, 62, 62, 72, 67, 57, 68, 67, 72, 65, 61, 60, 71, 67, 59, 65, 52, 65, 60, 67, 42, 63, 70, 82, 75, 76, 58, 69, 69, 66, 81, 69, 71, 63, 80, 77, 68, 78, 50, 66, 59, 63, 75, 72, 67, 66, 57, 76, 71, 74, 64, 64, 80, 64, 59, 73, 57, 76, 60, 68, 62, 53, 64, 51, 72, 45, 55, 68, 46, 61, 65, 65, 69, 51, 58, 67, 59, 62, 59, 56, 66, 62, 71, 60, 66, 54, 65, 67, 57, 68, 76, 54, 58, 54, 70, 63, 57, 64, 67, 76, 61, 49, 67, 67, 64, 70, 49, 49, 68, 54, 50, 60, 61, 68, 65, 62, 50, 60, 55, 65, 60, 61, 58, 58, 67, 54, 54, 63, 58, 70, 63, 46, 67, 44, 66, 53, 52, 49, 49, 55, 63, 55, 51, 62, 62, 52, 49, 60, 68, 48, 46, 56, 62, 69, 58, 56, 58, 53, 57, 45, 49, 53, 51, 48, 58, 54, 52, 59, 64, 58, 40, 48, 58, 55, 65, 52, 47, 61, 51, 62, 46, 49, 66, 75, 59, 60, 56, 89, 53, 59, 56, 49, 71, 48, 51, 63, 50, 60, 47, 64, 58, 52, 53, 53, 58, 66, 50, 60, 65, 56, 49, 52, 72, 55, 49, 53, 53, 65, 55, 55, 58, 52, 59, 49, 61, 54, 48, 57, 50, 53, 66, 49, 50, 52, 54, 70, 50, 56, 41, 53, 52, 45, 65, 53, 50, 54, 49, 53, 42, 55, 52, 42, 65, 44, 50, 49, 48, 55, 50, 54, 41, 45, 57, 63, 42, 54, 50, 54, 57, 47, 62, 42, 48, 47, 52, 51, 36, 51, 45, 48, 46, 43, 54, 45, 63, 56, 45, 42, 49, 66, 43, 46, 55, 41, 49, 53, 43, 60, 38, 59, 45, 47, 50, 47, 56, 46, 36, 48, 59, 59, 59, 39, 51, 45, 47, 41, 44, 62, 43, 46, 56, 55, 51, 53, 51, 44, 37, 47, 53, 48, 45, 42, 53, 49, 50, 45, 52, 62, 50, 55, 37, 45, 49, 48, 51, 47, 51, 49, 48, 46, 45, 42, 45, 44, 56, 45, 41, 57, 45, 43, 52, 49, 44, 52, 52, 55, 50, 54, 53, 52, 48, 45, 50, 48, 59, 54, 43, 40, 41, 43, 43, 42, 46, 50, 33, 60, 47, 47, 55, 36, 55, 46, 58, 49, 51, 60, 46, 44, 43, 41, 47, 42, 47, 47, 48, 40, 44, 45, 46, 42, 46, 44, 49, 42, 45, 44, 46, 49, 46, 45, 50, 40, 50, 43, 51, 55, 42, 42, 45, 38, 42, 48, 61, 43, 39, 43, 32, 48, 41, 37, 42, 29, 46, 40, 53, 54, 39, 46, 44, 37, 51, 40, 47, 47, 53, 54, 42, 53, 50, 45, 38, 42, 47, 44, 45, 36, 37, 40, 47, 44, 35, 43, 53, 35, 50, 46, 37, 41, 37, 48, 40, 38, 40, 51, 39, 46, 42, 48, 51, 54, 42, 40, 50, 45, 41, 49, 45, 44, 49, 46, 38, 50, 59, 43, 48, 45, 40, 61, 36, 44, 42, 39, 37, 40, 39, 39, 42, 44, 31, 46, 45, 37, 45, 44, 54, 49, 37, 54, 46, 45, 47, 38, 53, 52, 40, 48, 45, 49, 47, 49, 47, 41, 47, 41, 51, 50, 42, 46, 49, 38, 46, 35, 42, 49, 33, 42, 40, 73, 40, 46, 53, 40, 43, 43, 53, 48, 37, 57, 37, 40, 52, 49, 38, 34, 44, 39, 37, 48, 41, 37, 38, 35, 37, 40, 39, 38, 28, 41, 37, 39, 48, 34, 46, 31, 34, 49, 37, 45, 43, 42, 29, 37, 48, 45, 38, 41, 35, 43, 40, 52, 37, 44, 44, 35, 39, 48, 49, 44, 42, 35, 58, 31, 45, 41, 49, 49, 43, 51, 47, 42, 50, 40, 48, 43, 38, 43, 38, 43, 37, 48, 49, 35, 41, 49, 34, 46, 43, 50, 43, 48, 41, 42, 45, 44, 49, 39, 38, 50, 41, 36, 37, 33, 44, 35, 46, 37, 39, 47, 42, 41, 46, 36, 45, 41, 43, 45, 36, 45, 38, 44, 39, 45, 48, 32, 50, 31, 40, 56, 38, 47, 37, 45, 38, 31, 46, 31, 32, 44, 36, 36, 40, 44, 41, 35, 37, 40, 37, 37, 34, 37, 44, 39, 47, 44, 35, 32, 34, 35, 43, 39, 43, 36, 48, 31, 44, 34, 37, 41, 33, 44, 47, 36, 37, 35, 38, 41, 36, 43, 39, 36, 33, 35, 43, 39, 37, 31, 36, 40, 37, 40, 41, 31, 69, 34, 38, 29, 31, 68, 34, 37, 46, 33, 38, 24, 38, 42, 29, 48, 43, 45, 49, 40, 40, 37, 39, 41, 31, 39, 39, 37, 35, 31, 50, 39, 42, 35, 33, 37, 41, 31, 43, 28, 44, 36, 40, 42, 38, 39, 42, 40, 37, 36, 41, 30, 33, 40, 37, 37, 39, 32, 42, 37, 39, 40, 32, 41, 36, 32, 33, 33, 23, 29, 40, 38, 24, 36, 28, 45, 31, 35, 35, 27, 39, 29, 33, 34, 27, 37, 40, 31, 32, 34, 38, 35, 34, 42, 33, 29, 36, 40, 37, 30, 54, 32, 28, 44, 32, 34, 26, 43, 34, 30, 49, 38, 33, 31, 23, 30, 34, 35, 37, 30, 70, 30, 36, 26, 34, 35, 27, 36, 23, 31, 31, 34, 36, 34, 27, 44, 38, 46, 35, 30, 40, 30, 36, 38, 35, 41, 28, 26, 40, 32, 36, 28, 34, 31, 35, 38, 40, 37, 33, 34, 41, 37, 32, 34, 30, 35, 33, 34, 27, 32, 43, 35, 35, 34, 31, 49, 36, 34, 34, 25, 28, 33, 32, 40, 27, 48, 34, 37, 43, 30, 32, 36, 51, 48, 35, 35, 42, 34, 38, 30, 29, 36, 39, 35, 26, 35, 33, 25, 36, 26, 38, 29, 34, 24, 29, 44, 29, 30, 38, 30, 29, 36, 32, 38, 35, 40, 32, 36, 30, 21, 41, 31, 28, 30, 28, 30, 28, 27, 39, 29, 43, 23, 34, 27, 29, 42, 28, 35, 27, 30, 52, 38, 30, 35, 32, 31, 27, 19, 35, 26, 49, 29, 29, 25, 28, 29, 29, 31, 31, 30, 34, 35, 30, 31, 30, 36, 31, 30, 33, 26, 36, 35, 26, 35, 32, 31, 24, 31, 41, 30, 41, 30, 50, 30, 29, 37, 34, 30, 32, 26, 43, 26, 32, 35, 20, 29, 32, 26, 23, 26, 34, 24, 23, 29, 16, 38, 34, 32, 28, 26, 31, 30, 36, 33, 28, 25, 26, 28, 22, 31, 17, 32, 33, 30, 22, 40, 23, 31, 29, 19, 33, 30, 29, 31, 30, 27, 28, 26, 31, 30, 28, 31, 31, 32, 31, 30, 33, 31, 40, 31, 25, 17, 33, 30, 34, 32, 28, 31, 35, 23, 28, 30, 36, 19, 24, 31, 29, 36, 32, 18, 24, 21, 30, 35, 21, 36, 34, 38, 25, 31, 28, 20, 29, 30, 16, 33, 23, 26, 33, 19, 27, 25, 26, 15, 16, 30, 27, 35, 35, 27, 36, 36, 35, 25, 21, 32, 30, 33, 29, 23, 37, 29, 23, 26, 19, 33, 21, 35, 32, 19, 25, 26, 31, 25, 28, 30, 21, 27, 25, 21, 26, 23, 17, 36, 22, 21, 30, 26, 33, 25, 33, 31, 38, 38, 22, 18, 28, 25, 17, 26, 41, 20, 23, 30, 27, 30, 26, 27, 18, 25, 23, 26, 17, 36, 24, 32, 30, 26, 33, 17, 30, 27, 24, 18, 16, 47, 23, 26, 37, 25, 30, 31, 28, 30, 17, 34, 25, 28, 35, 25, 29, 27, 42, 28, 26, 32, 30, 38, 34, 33, 31, 22, 36, 31, 22, 37, 39, 28, 32, 26, 39, 34, 29, 42, 36, 33, 23, 36, 29, 26, 29, 26, 32, 33, 29, 32, 34, 27, 30, 21, 26, 21, 35, 27, 23, 38, 25, 28, 19, 31, 24, 26, 25, 29, 32, 29, 35, 32, 35, 26, 31, 23, 27, 36, 16, 31, 23, 26, 29, 26, 31, 19, 34, 21, 24, 33, 24, 20, 16, 35, 34, 22, 34, 44, 29, 37, 18, 33, 31, 24, 28, 23, 27, 22, 32, 31, 23, 33, 21, 23, 33, 24, 34, 26, 22, 36, 27, 31, 23, 25, 25, 30, 35, 36, 28, 25, 22, 30, 41, 25, 42, 34, 28, 36, 22, 39, 22, 30, 39, 25, 34, 32, 26, 27, 28, 32, 28, 31, 29, 18, 31, 31, 28, 35, 27, 31, 31, 27, 36, 13, 34, 34, 30, 28, 32, 26, 24, 38, 32, 25, 48, 26, 32, 24, 28, 32, 14, 31, 36, 21, 35, 35, 21, 37, 34, 33, 36, 32, 27, 24, 43, 30, 36, 28, 16, 30, 33, 25, 39, 27, 34, 33, 35, 35, 28, 31, 36, 28, 29, 30, 34, 29, 27, 35, 25, 44, 28, 26, 16, 29, 44, 31, 29, 32, 23, 35, 36, 31, 36, 20, 30, 32, 37, 29, 29, 37, 34, 26, 34, 30, 28, 29, 35, 13, 24, 37, 27, 31, 28, 25, 41, 19, 31, 25, 26, 40, 29, 28, 35, 25, 39, 24, 28, 30, 23, 38, 25, 18, 38, 24, 21, 26, 30, 25, 18, 30, 32, 30, 40, 32, 42, 26, 60, 25, 29, 25, 25, 32, 36, 25, 31, 31, 40, 20, 25, 36, 38, 35, 38, 29, 35, 26, 30, 25, 27, 29, 22, 32, 30, 27, 44, 28, 35, 24, 29, 32, 30, 31, 34, 29, 35, 26, 26, 33, 24, 31, 29, 20, 28, 27, 38, 21, 24, 26, 21, 25, 30, 39, 10, 19, 33, 25, 30, 28, 16, 29, 29, 26, 28, 25, 34, 28, 33, 30, 15, 25, 29, 26, 25, 19, 36, 27, 28, 25, 23, 27, 31, 22, 10, 20, 29, 31, 30, 22, 25, 26, 23, 26, 29, 31, 26, 31, 25, 24, 28, 32, 22, 28, 31, 13, 29, 25, 29, 33, 31, 28, 17, 32, 29, 19, 29, 26, 26, 20, 30, 26, 22, 19, 24, 26, 31, 26, 29, 25, 9, 32, 28, 15, 26, 25, 34, 26, 31, 27, 26, 33, 10, 35, 39, 21, 31, 21, 37, 26, 12, 31, 30, 28, 17, 27, 35, 26, 34, 32, 24, 35, 30, 28, 27, 27, 29, 28, 33, 35, 26, 31, 16, 27, 19, 15, 31, 20, 24, 31, 23, 22, 19, 21, 37, 27, 17, 26, 30, 19, 11, 30, 18, 26, 33, 6, 31, 21, 27, 21, 23, 26, 24, 28, 37, 16, 27, 25, 19, 27, 30, 28, 25, 34, 25, 26, 26, 19, 34, 21, 14, 23, 29, 27, 24, 24, 42, 26, 22, 27, 20, 33, 21, 36, 26, 14, 26, 27, 27, 29, 20, 18, 25, 28, 26, 22, 23, 26, 30, 25, 23, 25, 15, 22, 5, 21, 17, 17, 29, 19, 25, 39, 29, 32, 29, 30, 29, 26, 32, 28, 24, 26, 15, 21, 17, 21, 26, 19, 29, 31, 17, 46, 25, 23, 18, 20, 31, 20, 17, 22, 12, 15, 18, 27, 24, 14, 24, 22, 20, 16, 18, 19, 11, 27, 19, 14, 19, 14, 18, 27, 17, 23, 19, 29, 25, 20, 30, 26, 25, 15, 20, 28, 25, 31, 25, 21, 32, 21, 13, 18, 9, 32, 24, 22, 20, 8, 29, 22, 17, 20, 26, 34, 20, 21, 28, 31, 30, 20, 26, 28, 19, 30, 29, 31, 20, 15, 28, 21, 33, 31, 24, 15, 31, 19, 25, 14, 29, 30, 29, 22, 4, 22, 18, 27, 29, 20, 30, 20, 26, 32, 22, 20, 34, 28, 27, 28, 35, 30, 39, 26, 23, 28, 30, 37, 30, 26, 30, 21, 25, 28, 25, 28, 33, 21, 26, 21, 13, 20, 45, 27, 16, 21, 17, 29, 20, 22, 17, 19, 31, 21, 25, 22, 22, 20, 25, 14, 42, 22, 32, 21, 24, 26, 22, 34, 27, 23, 25, 26, 29, 27, 25, 22, 19, 29, 30, 20, 29, 26, 31, 27, 18, 27, 10, 35, 44, 27, 31, 14, 31, 28, 18, 20, 17, 28, 26, 13, 30, 26, 34, 27, 32, 35, 25, 27, 29, 21, 20, 14, 25, 22, 20, 22, 24, 22, 27, 23, 25, 23, 30, 26, 23, 23, 38, 23, 35, 31, 34, 31, 31, 34, 32, 34, 30, 31, 35, 27, 47, 30, 26, 33, 23, 39, 23, 30, 33, 20, 36, 27, 41, 36, 30, 29, 32, 23, 34, 27, 36, 33, 26, 31, 26, 32, 17, 26, 30, 13, 33, 34, 26, 27, 24, 32, 26, 30, 26, 32, 36, 20, 27, 23, 23, 27, 25, 28, 24, 16, 25, 34, 21, 21, 25, 37, 13, 34, 26, 23, 27, 21, 24, 27, 20, 30, 13, 29, 19, 33, 30, 20, 38, 30, 19, 34, 23, 27, 25, 29, 29, 27, 32, 29, 24, 32, 19, 30, 23, 29, 30, 31, 25, 33, 27, 35, 31, 27, 35, 32, 35, 29, 33, 22, 20, 26, 24, 28, 25, 14, 49, 27, 26, 28, 24, 41, 21, 23, 30, 23, 26, 26, 25, 31, 20, 36, 20, 38, 25, 22, 33, 22, 28, 22, 19, 28, 32, 18, 23, 23, 23, 27, 21, 34, 7, 26, 21, 29, 12, 21, 37, 25, 27, 28, 21, 25, 30, 41, 28, 19, 33, 23, 34, 30, 16, 44, 25, 42, 29, 19, 22, 20, 18, 29, 33, 28, 30, 22, 13, 28, 39, 23, 27, 33, 18, 28, 32, 34, 27, 22, 31, 28, 30, 30, 13, 31, 42, 22, 26, 15, 34, 23, 15, 30, 17, 15, 30, 30, 27, 24, 22, 28, 21, 24, 20, 26, 27, 18, 21, 28, 26, 9, 29, 20, 21, 45, 25, 24, 13, 22, 29, 28, 29, 28, 31, 28, 21, 31, 35, 19, 32, 28, 20, 29, 14, 31, 28, 29, 27, 22, 20, 30, 25, 26, 20, 17, 26, 23, 32, 30, 46, 24, 31, 22, 18, 33, 28, 48, 27, 17, 31, 28, 23, 25, 22, 37, 19, 40, 31, 21, 33, 23, 23, 23, 26, 24, 26, 29, 16, 25, 22, 21, 51, 11, 25, 30, 14, 30, 26, 27, 35, 23, 28, 25, 21, 23, 34, 22, 25, 20, 23, 23, 20, 29, 19, 28, 20, 26, 33, 22, 30, 32, 27, 33, 19, 24, 19, 38, 35, 21, 30, 29, 36, 28, 31, 37, 30, 28, 33, 23, 21, 34, 30, 33, 27, 41, 27, 25, 31, 28, 25, 28, 32, 31, 34, 29, 40, 43, 36, 23, 27, 29, 34, 29, 30, 38, 27, 35, 29, 25, 25, 33, 21, 16, 12, 30, 27, 28, 30, 27, 27, 28, 28, 17, 25, 43, 20, 27, 27, 10, 38, 16, 31, 21, 31, 64, 33, 26, 28, 21, 32, 26, 32, 22, 28, 36, 19, 28, 31, 23, 21, 29, 34, 34, 25, 33, 26, 25, 34, 24, 43, 28, 31, 34, 32, 36, 34, 24, 30, 22, 35, 33, 34, 25, 29, 28, 26, 29, 31, 19, 30, 25, 33, 34, 24, 30, 29, 38, 29, 23, 26, 23, 32, 30, 29, 31, 26, 22, 27, 16, 21, 25, 30, 30, 22, 32, 25, 34, 33, 26, 33, 29, 30, 34, 26, 25, 23, 30, 32, 28, 31, 22, 28, 18, 21, 30, 26, 30, 22, 29, 34, 11, 23, 21, 26, 29, 21, 26, 25, 22, 32, 24, 28, 24, 15, 26, 14, 24, 28, 28, 15, 18, 30, 18, 21, 23, 27, 30, 9, 20, 29, 24, 21, 24, 19, 41, 28, 20, 24, 10, 38, 30, 22, 26, 16, 30, 27, 35, 15, 17, 29, 18, 34, 34, 27, 30, 22, 25, 18, 25, 22, 34, 32, 28, 23, 32, 22, 29, 23, 28, 33, 24, 16, 18, 16, 29, 27, 23, 35, 27, 31, 38, 30, 22, 27, 25, 18, 28, 30, 23, 33, 29, 28, 24, 21, 22, 30, 29, 23, 15, 22, 26, 16, 35, 26, 23, 23, 32, 22, 9, 22, 25, 22, 31, 29, 27, 23, 21, 30, 25, 17, 27, 38, 28, 18, 26, 25, 27, 30, 28, 19, 19, 24, 20, 24, 34, 18, 21, 31, 15, 25, 25, 18, 29, 12, 29, 29, 32, 13, 43, 26, 14, 31, 21, 17, 32, 25, 18, 28, 15, 26, 27, 20, 28, 19, 24, 27, 34, 26, 19, 26, 22, 27, 17, 16, 28, 12, 16, 19, 22, 22, 8, 26, 22, 18, 29, 37, 11, 26, 23, 30, 27, 25, 29, 19, 23, 20, 27, 24, 8, 19, 23, 29, 22, 5, 21, 23, 28, 22, 18, 21, 19, 19, 2, 19, 23, 18, 25, 7, 14, 18, 13, 27, 19, 19, 15, 16, 27, 17, 15, 19, 29, 19, 21, 24, 26, 19, 25, 5, 9, 25, 19, 30, 27, 12, 35, 26, 34, 24, 19, 30, 26, 20, 16, 18, 37, 13, 27, 26, 16, 19, 22, 30, 20, 24, 22, 20, 24, 18, 21, 20, 20, 26, 22, 14, 35, 17, 20, 19, 19, 20, 28, 39, 28, 20, 28, 31, 22, 28, 11, 12, 21, 26, 16, 6, 10, 19, 20, 17, 21, 30, 14, 27, 14, 26, 49, 11, 33, 26, 15, 21, 16, 20, 20, 12, 21, 18, 29, 27, 13, 35, 30, 13, 9, 14, 29, 17, 33, 19, 16, 30, 21, 28, 9, 19, 21, 16, 28, 26, 16, 31, 26, 17, 20, 25, 22, 27, 24, 5, 15, 31, 13, 20, 23, 14, 23, 25, 20, 19, 23, 33, 24, 22, 16, 11, 22, 19, 17, 13, 16, 26, 33, 20, 22, 19, 36, 19, 8, 12, 21, 37, 8, 21, 7, 7, 17, 17, 23, 13, 23, 20, 16, 26, 28, 14, 15, 27, 11, 13, 16, 14, 21, 21, 16, 26, 18, 19, 27, 24, 23, 39, 9, 20, 28, 26, 14, 12, 23, 13, 22, 40, 26, 32, 16, 20, 35, 22, 27, 26, 14, 19, 24, 21, 17, 18, 28, 20, 23, 20, 8, 28, 15, 39, 23, 12, 23, 14, 25, 23, 14, 12, 21, 27, 11, 14, 24, 19, 24, 25, 23, 26, 23, 22, 17, 18, 17, 20, 23, 21, 24, 22, 22, 25, 32, 14, 31, 27, 35, 26, 21, 26, 23, 27, 4, 16, 29, 36, 17, 12, 9, 24, 31, 22, 29, 20, 30, 21, 17, 23, 19, 27, 22, 14, 28, 21, 26, 33, 23, 27, 24, 33, 37, 29, 37, 14, 25, 22, 17, 21, 26, 35, 29, 21, 24, 27, 22, 20, 21, 22, 17, 34, 29, 21, 30, 21, 23, 19, 28, 13, 17, 17, 23, 14, 17, 27, 29, 19, 25, 24, 25, 28, 26, 24, 20, 9, 16, 18, 26, 17, 21, 26, 16, 26, 27, 11, 28, 24, 22, 26, 17, 33, 20, 19, 16, 6, 21, 19, 29, 22, 21, 19, 14, 27, 24, 14, 21, 25, 20, 24, 22, 27, 16, 26, 7, 24, 22, 19, 23, 27, 22, 25, 21, 25, 21, 26, 30, 20, 14, 30, 20, 19, 27, 14, 22, 18, 28, 29, 24, 26, 29, 38, 20, 31, 33, 25, 28, 19, 42, 31, 20, 29, 27, 40, 29, 19, 29, 16, 43, 24, 20, 27, 15, 28, 23, 11, 21, 24, 29, 27, 21, 31, 27, 24, 27, 25, 23, 32, 23, 18, 20, 26, 32, 20, 15, 17, 21, 35, 21, 26, 21, 27, 18, 25, 22, 16, 20, 32, 23, 19, 7, 30, 26, 26, 33, 25, 28, 24, 28, 31, 25, 37, 29, 26, 34, 22, 34, 24, 28, 21, 13, 36, 31, 25, 26, 17, 21, 21, 29, 35, 25, 30, 27, 27, 29, 26, 26, 28, 26, 31, 21, 33, 29, 31, 32, 25, 39, 26, 17, 33, 21, 34, 19, 32, 29, 12, 24, 31, 28, 25, 19, 37, 23, 20, 28, 19, 21, 24, 27, 25, 23, 33, 20, 24, 26, 18, 23, 19, 17, 12, 13, 25, 26, 20, 24, 20, 20, 12, 14, 24, 23, 26, 15, 27, 19, 19, 42, 23, 30, 20, 14, 26, 26, 18, 27, 12, 17, 20, 30, 18, 20, 26, 23, 28, 22, 0, 27, 18, 20, 27, 22, 27, 29, 19, 21, 19, 28, 22, 22, 27, 15, 25, 21, 21, 23, 20, 28, 24, 17, 35, 16, 21, 29, 27, 22, 11, 23, 37, 29, 22, 8, 26, 22, 30, 28, 13, 40, 22, 22, 19, 16, 30, 21, 34, 23, 11, 30, 30, 44, 33, 29, 27, 17, 26, 28, 31, 40, 27, 37, 27, 13, 27, 28, 33, 33, 22, 17, 24, 29, 31, 38, 38, 29, 22, 19, 21, 30, 30, 34, 22, 9, 28, 22, 26, 33, 31, 32, 23, 24, 20, 15, 47, 45, 27, 30, 28, 30, 25, 45, 38, 24, 28, 15, 22, 23, 26, 34, 31, 31, 23, 20, 26, 28, 32, 34, 34, 26, 21, 29, 33, 35, 38, 34, 35, 18, 20, 28, 43, 45, 34, 21, 32, 28, 38, 34, 33, 51, 28, 26, 34, 29, 32, 43, 49, 17, 22, 31, 27, 30, 43, 35, 46, 23, 23, 25, 31, 39, 40, 37, 27, 29, 21, 32, 41, 46, 29, 19, 23, 35, 38, 40, 44, 33, 19, 32, 22, 41, 38, 41, 37, 16, 15, 16, 27, 50, 104, 46, 27, 25, 39, 34, 53, 44, 46, 25, 14, 30, 33, 44, 55, 34, 34, 18, 34, 41, 37, 52, 49, 47, 29, 31, 33, 33, 57, 46, 27, 38, 22, 35, 28, 40, 53, 35, 30, 22, 22, 46, 42, 46, 44, 19, 25, 30, 43, 47, 48, 52, 29, 26, 35, 30, 48, 46, 49, 44, 29, 26, 34, 41, 49, 50, 41, 26, 30, 42, 38, 52, 56, 54, 29, 31, 46, 45, 54, 60, 45, 32, 30, 37, 49, 50, 57, 41, 46, 33, 39, 40, 55, 64, 49, 31, 42, 37, 44, 52, 54, 51, 32, 27, 45, 41, 47, 56, 56, 35, 40, 33, 44, 50, 49, 50, 49, 36, 42, 42, 43, 58, 60, 45, 41, 33, 45, 52, 61, 56, 37, 49, 40, 38, 50, 56, 69, 56, 45, 39, 44, 46, 54, 58, 62, 51, 84, 36, 52, 66, 53, 51, 45, 44, 47, 52, 78, 65, 63, 52, 40, 50, 52, 61, 61, 55, 55, 37, 47, 43, 48, 81, 61, 51, 51, 44, 42, 53, 62, 73, 54, 46, 52, 56, 52, 49, 70, 52, 50, 56, 46, 54, 55, 66, 47, 48, 50, 56, 51, 87, 68, 57, 48, 52, 53, 64, 64, 50, 60, 66, 49, 57, 53, 55, 70, 49, 55, 45, 75, 57, 60, 67, 76, 51, 63, 46, 54, 70, 62, 82, 61, 58, 50, 66, 68, 65, 68, 48, 56, 62, 60, 73, 70, 79, 63, 56, 66, 65, 62, 83, 68, 78, 54, 81, 77, 54, 75, 67, 83, 51, 64, 79, 69, 62, 70, 78, 75, 71, 74, 72, 73, 82, 61, 78, 67, 76, 75, 65, 79, 79, 68, 74, 84, 65, 76, 73, 83, 89, 70, 67, 75, 92, 81, 79, 67, 78, 78, 69, 77, 89, 69, 78, 83, 81, 64, 68, 73, 79, 75, 77, 67, 92, 75, 80, 84, 84, 76, 77, 79, 79, 82, 82, 86, 93, 85, 70, 88, 88, 90, 77, 72, 82, 87, 88, 90, 79, 75, 76, 86, 89, 71, 91, 85, 70, 85, 81, 85, 78, 96, 88, 82, 92, 72, 83, 84, 77, 80, 85, 73, 87, 84, 78, 84, 88, 87, 75, 89, 91, 86, 81, 80, 90, 85, 81, 84, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 50, 73, 88, 57, 44, 49, 104, 90, 104, 115, 122, 122, 105, 95, 97, 109, 99, 93, 95, 100, 117, 108, 89, 83, 60, 70, 92, 90, 107, 110, 109, 99, 92, 120, 125, 116, 110, 105, 113, 102, 89, 86, 106, 134, 115, 55, 23, 48, 30, 31, 33, 36, 26, 38, 30, 39, 51, 30, 27, 46, 37, 34, 36, 44, 87, 85, 42, 83, 76, 74, 40, 79, 63, 103, 111, 110, 111, 111, 115, 112, 112, 119, 118, 115, 121, 116, 115, 114, 117, 118, 121, 120, 115, 117, 117, 120, 119, 117, 123, 117, 122, 119, 117, 120, 120, 120, 117, 117, 120, 121, 120, 121, 120, 118, 119, 121, 120, 120, 121, 123, 121, 121, 120, 122, 118, 120, 123, 121, 122, 122, 120, 120, 116, 122, 121, 120, 121, 120, 120, 121, 121, 120, 119, 120, 120, 122, 121, 120, 125, 118, 121, 119, 119, 122, 120, 121, 117, 119, 123, 122, 120, 120, 117, 128, 121, 121, 121, 120, 119, 121, 121, 122, 118, 119, 117, 121, 119, 119, 118, 116, 121, 121, 118, 116, 118, 119, 122, 118, 117, 121, 123, 120, 119, 120, 120, 118, 120, 120, 118, 119, 117, 121, 117, 118, 117, 121, 119, 116, 121, 120, 122, 120, 117, 121, 116, 120, 117, 119, 118, 120, 118, 116, 116, 119, 119, 120, 115, 117, 121, 118, 120, 118, 117, 116, 116, 121, 119, 116, 121, 119, 117, 119, 117, 120, 117, 119, 117, 115, 118, 118, 117, 120, 117, 116, 118, 117, 122, 121, 119, 114, 117, 119, 117, 119, 117, 116, 118, 117, 115, 115, 116, 118, 114, 116, 116, 119, 115, 115, 117, 119, 117, 115, 116, 121, 117, 116, 116, 117, 115, 118, 120, 116, 116, 117, 115, 117, 115, 114, 116, 120, 118, 117, 115, 117, 116, 114, 116, 117, 120, 118, 114, 115, 115, 118, 118, 116, 115, 115, 115, 116, 117, 115, 114, 117, 115, 115, 114, 115, 114, 115, 116, 114, 117, 116, 116, 116, 112, 112, 114, 116, 114, 116, 111, 116, 117, 115, 111, 114, 115, 114, 114, 115, 114, 115, 115, 115, 114, 114, 114, 115, 116, 115, 112, 113, 114, 111, 114, 112, 116, 115, 115, 115, 112, 113, 114, 116, 114, 114, 115, 113, 113, 113, 111, 114, 115, 112, 113, 110, 115, 112, 113, 112, 111, 113, 113, 111, 111, 111, 116, 110, 114, 114, 112, 111, 111, 117, 110, 110, 111, 112, 113, 110, 110, 113, 109, 111, 114, 114, 114, 110, 111, 115, 113, 111, 110, 112, 114, 108, 111, 115, 111, 112, 111, 109, 109, 114, 107, 110, 111, 114, 113, 110, 112, 111, 115, 137, 115, 111, 110, 109, 115, 110, 111, 111, 111, 109, 110, 107, 109, 111, 110, 110, 110, 111, 110, 111, 110, 104, 116, 111, 110, 109, 110, 111, 108, 110, 110, 107, 106, 110, 109, 107, 110, 111, 108, 111, 112, 107, 111, 111, 107, 112, 109, 106, 108, 107, 111, 110, 111, 107, 109, 113, 106, 110, 111, 106, 105, 108, 110, 110, 109, 108, 105, 107, 108, 108, 107, 110, 108, 105, 105, 110, 105, 108, 106, 103, 107, 105, 102, 105, 107, 105, 105, 109, 103, 105, 103, 103, 107, 103, 105, 105, 103, 102, 105, 103, 106, 106, 106, 104, 109, 104, 101, 106, 100, 105, 108, 105, 106, 101, 108, 105, 106, 106, 106, 105, 107, 98, 106, 104, 103, 100, 103, 104, 104, 105, 103, 103, 102, 104, 105, 104, 100, 104, 98, 107, 102, 100, 104, 99, 103, 106, 102, 103, 104, 105, 101, 106, 103, 104, 101, 100, 100, 100, 104, 104, 100, 104, 103, 100, 104, 98, 100, 105, 103, 101, 105, 98, 102, 102, 99, 102, 98, 101, 103, 101, 104, 99, 103, 100, 98, 101, 100, 99, 100, 101, 98, 100, 105, 102, 104, 104, 100, 105, 104, 108, 102, 104, 98, 103, 105, 102, 101, 105, 100, 102, 98, 99, 102, 105, 100, 100, 102, 104, 101, 100, 100, 104, 105, 102, 103, 105, 102, 97, 103, 98, 100, 100, 100, 99, 100, 102, 97, 99, 111, 118, 101, 96, 105, 98, 101, 101, 95, 105, 100, 104, 103, 97, 97, 100, 98, 104, 102, 100, 100, 101, 99, 97, 102, 105, 98, 96, 95, 100, 99, 99, 102, 97, 104, 103, 99, 101, 101, 103, 94, 102, 103, 91, 104, 103, 107, 99, 99, 102, 98, 100, 102, 99, 104, 103, 100, 100, 101, 104, 100, 101, 98, 96, 99, 100, 99, 96, 98, 97, 98, 101, 90, 98, 99, 92, 101, 101, 93, 103, 100, 96, 98, 95, 99, 97, 95, 93, 97, 100, 98, 99, 99, 98, 101, 99, 100, 99, 96, 98, 99, 97, 98, 91, 100, 89, 95, 99, 91, 100, 95, 95, 99, 95, 94, 97, 93, 97, 98, 97, 92, 103, 96, 90, 102, 94, 93, 99, 95, 93, 102, 93, 95, 91, 89, 100, 96, 98, 86, 98, 93, 92, 99, 91, 96, 98, 97, 91, 94, 96, 94, 96, 84, 88, 89, 93, 98, 94, 87, 101, 93, 90, 95, 89, 96, 96, 99, 96, 92, 88, 91, 94, 85, 91, 94, 93, 98, 94, 82, 96, 100, 86, 86, 87, 98, 92, 90, 93, 88, 87, 83, 89, 85, 88, 89, 92, 97, 91, 91, 93, 87, 96, 97, 83, 97, 97, 91, 98, 89, 101, 90, 92, 86, 81, 99, 87, 88, 92, 86, 87, 91, 91, 92, 81, 93, 87, 87, 98, 91, 90, 95, 87, 79, 90, 98, 93, 92, 92, 88, 89, 94, 87, 95, 83, 91, 95, 87, 88, 83, 88, 93, 83, 87, 87, 93, 105, 95, 87, 91, 92, 92, 82, 88, 74, 98, 83, 83, 67, 82, 78, 89, 82, 83, 81, 93, 85, 90, 91, 85, 85, 84, 82, 93, 81, 88, 74, 82, 88, 87, 91, 78, 90, 84, 81, 87, 85, 87, 83, 82, 99, 84, 84, 89, 87, 89, 85, 83, 86, 92, 82, 78, 82, 81, 80, 86, 92, 88, 91, 78, 89, 84, 82, 61, 82, 90, 83, 81, 73, 85, 87, 81, 92, 79, 81, 88, 73, 84, 91, 85, 80, 85, 83, 84, 82, 83, 68, 77, 91, 85, 74, 86, 87, 86, 86, 76, 76, 88, 77, 78, 78, 89, 86, 64, 72, 84, 74, 82, 82, 70, 80, 73, 87, 84, 79, 71, 81, 85, 69, 70, 85, 77, 88, 82, 87, 82, 80, 78, 87, 84, 79, 79, 76, 83, 73, 78, 91, 84, 69, 71, 80, 69, 83, 81, 66, 77, 86, 72, 88, 71, 96, 84, 80, 89, 74, 85, 82, 84, 83, 69, 87, 78, 85, 86, 67, 86, 87, 77, 68, 72, 82, 78, 71, 78, 73, 89, 78, 62, 88, 75, 77, 79, 73, 72, 67, 80, 82, 72, 67, 78, 77, 77, 82, 78, 70, 78, 73, 79, 74, 77, 88, 72, 72, 70, 73, 89, 67, 70, 69, 69, 74, 71, 78, 70, 66, 77, 78, 78, 68, 65, 67, 66, 63, 79, 67, 79, 63, 71, 69, 77, 63, 70, 80, 71, 81, 79, 68, 81, 76, 64, 84, 74, 74, 86, 55, 80, 77, 64, 73, 78, 62, 61, 76, 70, 77, 76, 83, 73, 67, 71, 63, 64, 79, 55, 60, 78, 55, 72, 68, 57, 77, 65, 60, 70, 55, 63, 65, 62, 62, 65, 75, 65, 75, 60, 65, 73, 69, 68, 64, 46, 67, 65, 75, 73, 60, 59, 68, 78, 63, 59, 67, 60, 66, 69, 62, 73, 66, 69, 79, 63, 80, 62, 68, 70, 74, 81, 67, 63, 68, 72, 67, 58, 65, 54, 71, 74, 64, 64, 49, 64, 74, 59, 64, 61, 68, 60, 54, 61, 71, 58, 72, 58, 79, 52, 52, 68, 57, 57, 69, 51, 58, 67, 66, 54, 67, 71, 57, 70, 71, 52, 59, 61, 72, 67, 57, 68, 69, 61, 80, 70, 62, 54, 66, 56, 59, 62, 61, 63, 67, 51, 64, 63, 56, 64, 53, 63, 58, 60, 68, 53, 65, 62, 81, 60, 55, 57, 60, 61, 58, 51, 59, 62, 69, 55, 40, 63, 63, 52, 59, 56, 59, 68, 52, 55, 56, 63, 55, 55, 58, 54, 54, 52, 49, 52, 47, 69, 52, 56, 42, 53, 58, 49, 58, 53, 50, 59, 49, 53, 58, 48, 51, 54, 46, 68, 43, 51, 51, 61, 58, 55, 65, 60, 76, 54, 51, 54, 59, 49, 66, 59, 52, 60, 56, 55, 53, 59, 56, 49, 49, 54, 51, 55, 66, 52, 60, 78, 58, 67, 61, 41, 66, 51, 57, 47, 45, 71, 49, 46, 32, 55, 56, 47, 53, 65, 55, 48, 66, 67, 52, 55, 69, 47, 54, 50, 45, 53, 41, 49, 50, 40, 48, 49, 50, 56, 46, 61, 46, 59, 45, 53, 45, 42, 49, 61, 37, 55, 59, 82, 45, 39, 57, 49, 48, 49, 50, 48, 52, 45, 66, 38, 67, 62, 65, 54, 44, 47, 42, 54, 38, 47, 52, 51, 62, 51, 51, 61, 52, 54, 54, 45, 48, 49, 45, 47, 44, 58, 49, 46, 49, 41, 56, 47, 48, 46, 38, 52, 58, 47, 57, 41, 56, 60, 47, 43, 36, 59, 59, 50, 39, 45, 52, 46, 44, 48, 43, 41, 49, 43, 46, 43, 40, 49, 42, 62, 36, 43, 40, 60, 53, 44, 58, 45, 52, 49, 45, 43, 71, 51, 55, 48, 51, 47, 46, 49, 42, 46, 51, 47, 50, 44, 64, 51, 47, 50, 40, 61, 46, 49, 50, 52, 41, 44, 50, 48, 42, 46, 43, 57, 50, 43, 52, 54, 63, 46, 36, 48, 48, 47, 46, 39, 58, 52, 42, 42, 44, 41, 37, 53, 45, 49, 51, 42, 41, 44, 38, 53, 47, 47, 52, 42, 54, 40, 49, 40, 46, 47, 41, 49, 49, 36, 39, 44, 41, 44, 36, 45, 44, 46, 45, 43, 35, 48, 42, 42, 39, 38, 42, 43, 43, 38, 39, 48, 38, 43, 41, 42, 37, 34, 40, 34, 47, 38, 39, 52, 44, 64, 51, 45, 42, 42, 53, 42, 42, 41, 45, 45, 43, 42, 41, 44, 45, 52, 43, 40, 42, 57, 40, 43, 47, 35, 65, 46, 37, 47, 32, 43, 40, 43, 46, 40, 39, 35, 42, 37, 41, 43, 42, 46, 50, 39, 46, 39, 50, 49, 44, 40, 43, 45, 52, 38, 48, 39, 40, 35, 47, 56, 42, 39, 37, 40, 45, 45, 37, 39, 42, 46, 39, 43, 50, 44, 54, 44, 43, 41, 35, 51, 37, 38, 37, 35, 46, 36, 39, 49, 36, 34, 41, 41, 41, 41, 45, 39, 31, 40, 38, 57, 40, 40, 37, 33, 43, 36, 40, 38, 34, 41, 42, 40, 43, 37, 53, 42, 43, 45, 37, 46, 34, 38, 38, 39, 49, 34, 37, 43, 41, 32, 38, 40, 37, 40, 39, 38, 33, 35, 37, 39, 38, 39, 22, 37, 40, 28, 54, 45, 32, 31, 29, 43, 42, 34, 44, 46, 40, 37, 34, 52, 37, 39, 56, 35, 34, 43, 49, 39, 37, 40, 45, 36, 45, 41, 38, 39, 48, 40, 24, 47, 39, 45, 42, 38, 43, 43, 27, 49, 32, 43, 49, 40, 41, 31, 40, 41, 43, 39, 37, 48, 41, 47, 45, 28, 39, 34, 44, 44, 35, 47, 54, 49, 39, 35, 46, 37, 50, 47, 36, 53, 46, 30, 39, 35, 49, 45, 36, 45, 38, 50, 39, 34, 37, 32, 45, 42, 35, 43, 32, 60, 37, 45, 38, 37, 41, 31, 43, 39, 30, 42, 40, 44, 41, 35, 54, 40, 43, 32, 28, 37, 44, 29, 42, 28, 40, 32, 34, 41, 38, 39, 38, 36, 37, 31, 49, 40, 37, 41, 33, 44, 30, 36, 48, 40, 43, 36, 36, 37, 34, 36, 38, 35, 38, 39, 43, 31, 61, 40, 42, 40, 41, 31, 41, 45, 44, 39, 42, 35, 29, 31, 35, 44, 43, 40, 44, 48, 40, 43, 38, 45, 33, 40, 46, 37, 45, 30, 25, 34, 34, 31, 35, 37, 34, 34, 42, 41, 44, 32, 35, 41, 33, 33, 28, 30, 34, 36, 38, 34, 36, 40, 37, 36, 35, 30, 38, 35, 32, 37, 27, 32, 36, 26, 39, 35, 32, 35, 36, 38, 33, 33, 39, 40, 46, 32, 36, 36, 34, 34, 36, 35, 35, 38, 33, 29, 49, 34, 32, 43, 34, 36, 38, 39, 38, 40, 39, 31, 28, 29, 31, 34, 37, 30, 36, 26, 33, 23, 32, 39, 31, 37, 34, 30, 28, 38, 48, 31, 29, 36, 28, 35, 32, 35, 38, 35, 36, 32, 40, 30, 37, 41, 40, 43, 36, 40, 60, 34, 38, 38, 32, 46, 40, 40, 40, 30, 41, 33, 40, 41, 33, 41, 34, 32, 41, 34, 34, 36, 40, 38, 29, 43, 39, 34, 36, 32, 32, 23, 52, 24, 28, 34, 37, 37, 38, 30, 41, 39, 41, 39, 26, 40, 40, 31, 28, 28, 32, 35, 37, 32, 28, 37, 33, 40, 37, 36, 40, 43, 29, 41, 32, 34, 33, 35, 23, 31, 33, 40, 41, 30, 33, 42, 24, 36, 33, 29, 34, 30, 34, 33, 16, 35, 28, 35, 44, 26, 38, 38, 29, 30, 37, 26, 41, 39, 30, 31, 43, 30, 38, 40, 22, 33, 22, 29, 33, 17, 29, 38, 29, 37, 28, 35, 21, 30, 29, 32, 35, 25, 27, 31, 27, 31, 24, 26, 9, 23, 34, 25, 21, 29, 29, 26, 26, 30, 29, 24, 24, 26, 40, 31, 26, 35, 23, 32, 30, 24, 31, 35, 32, 26, 29, 25, 30, 30, 20, 25, 40, 25, 23, 32, 23, 35, 27, 26, 27, 32, 20, 30, 37, 29, 27, 31, 29, 19, 29, 29, 29, 29, 23, 33, 23, 32, 28, 31, 26, 24, 24, 27, 45, 35, 20, 28, 22, 26, 30, 19, 28, 19, 22, 30, 23, 37, 23, 26, 28, 18, 29, 31, 11, 27, 22, 31, 26, 25, 28, 26, 31, 26, 26, 35, 15, 31, 23, 26, 18, 29, 33, 30, 28, 32, 22, 26, 30, 29, 16, 18, 25, 19, 30, 31, 23, 31, 21, 18, 17, 14, 41, 30, 32, 25, 23, 21, 25, 26, 28, 31, 44, 30, 34, 27, 23, 31, 22, 25, 33, 25, 19, 15, 28, 30, 27, 30, 24, 27, 36, 18, 30, 30, 21, 20, 17, 33, 29, 29, 21, 24, 23, 19, 26, 28, 27, 29, 15, 25, 30, 19, 25, 30, 28, 25, 32, 32, 25, 38, 36, 23, 34, 26, 28, 33, 17, 20, 28, 30, 27, 26, 27, 27, 22, 35, 28, 40, 29, 32, 17, 32, 29, 25, 27, 36, 26, 27, 31, 30, 34, 26, 34, 26, 24, 32, 25, 31, 28, 23, 30, 27, 30, 36, 38, 27, 23, 26, 19, 25, 36, 31, 39, 25, 24, 40, 31, 40, 18, 25, 44, 27, 25, 28, 31, 38, 30, 33, 29, 44, 31, 34, 30, 31, 28, 32, 23, 33, 32, 31, 23, 24, 39, 47, 42, 20, 29, 26, 29, 36, 35, 26, 32, 39, 24, 32, 24, 32, 17, 33, 20, 33, 35, 33, 29, 27, 25, 28, 37, 19, 24, 20, 36, 29, 20, 23, 29, 37, 24, 31, 31, 16, 33, 31, 23, 31, 29, 31, 16, 18, 31, 26, 28, 33, 24, 39, 24, 31, 28, 25, 10, 34, 50, 115, 79, 27, 25, 38, 19, 30, 33, 28, 37, 22, 32, 36, 23, 33, 27, 28, 16, 24, 29, 26, 34, 25, 20, 31, 34, 30, 30, 17, 29, 26, 15, 25, 33, 36, 24, 31, 27, 17, 44, 31, 28, 20, 28, 36, 34, 30, 28, 32, 26, 33, 28, 32, 22, 31, 29, 31, 31, 26, 22, 35, 27, 19, 31, 27, 30, 37, 23, 18, 30, 15, 19, 26, 18, 43, 32, 25, 26, 26, 37, 24, 33, 15, 14, 26, 24, 44, 29, 25, 27, 31, 29, 38, 10, 43, 32, 34, 28, 25, 42, 33, 39, 35, 23, 30, 34, 27, 29, 44, 40, 35, 33, 31, 30, 40, 23, 25, 29, 18, 27, 30, 36, 33, 28, 31, 33, 29, 29, 19, 35, 21, 29, 30, 20, 26, 25, 20, 35, 27, 32, 24, 23, 26, 22, 31, 29, 35, 22, 24, 30, 27, 24, 32, 22, 41, 23, 25, 10, 19, 19, 18, 36, 30, 23, 34, 29, 31, 34, 24, 38, 35, 29, 27, 19, 30, 33, 24, 21, 26, 35, 25, 30, 35, 15, 35, 34, 20, 31, 26, 32, 35, 39, 25, 18, 38, 30, 30, 31, 31, 35, 38, 37, 31, 33, 35, 28, 29, 30, 26, 25, 41, 27, 11, 22, 32, 24, 27, 39, 22, 30, 29, 40, 32, 25, 31, 29, 29, 40, 26, 31, 33, 24, 31, 17, 31, 22, 27, 26, 21, 30, 26, 27, 30, 18, 28, 30, 26, 28, 25, 30, 28, 16, 29, 17, 32, 16, 25, 17, 21, 33, 25, 27, 25, 29, 19, 36, 32, 30, 27, 23, 30, 23, 27, 11, 22, 29, 26, 11, 19, 30, 28, 31, 13, 17, 26, 29, 25, 32, 18, 30, 30, 23, 32, 28, 28, 25, 26, 29, 25, 29, 27, 31, 33, 30, 32, 29, 31, 29, 19, 26, 27, 18, 26, 28, 31, 18, 32, 19, 19, 29, 25, 33, 20, 21, 28, 19, 35, 29, 20, 31, 27, 26, 27, 23, 30, 24, 33, 31, 28, 31, 26, 35, 36, 18, 15, 24, 21, 24, 20, 34, 26, 24, 29, 2, 28, 20, 27, 29, 22, 27, 23, 26, 19, 16, 20, 26, 22, 26, 20, 24, 25, 29, 28, 31, 21, 25, 21, 29, 19, 30, 19, 26, 30, 18, 31, 28, 26, 31, 27, 33, 27, 17, 19, 24, 33, 25, 29, 27, 25, 25, 14, 18, 28, 11, 28, 18, 19, 26, 13, 22, 21, 27, 23, 4, 33, 18, 17, 17, 19, 28, 27, 26, 22, 14, 18, 20, 31, 26, 9, 27, 23, 13, 30, 18, 28, 26, 16, 23, 19, 35, 30, 23, 19, 15, 39, 25, 14, 23, 24, 29, 19, 25, 28, 22, 26, 17, 25, 23, 20, 27, 22, 17, 26, 15, 21, 23, 27, 31, 26, 34, 8, 29, 26, 18, 29, 18, 20, 7, 13, 29, 15, 19, 28, 11, 27, 29, 20, 24, 22, 27, 16, 29, 25, 11, 14, 26, 14, 19, 20, 18, 21, 29, 16, 12, 29, 25, 20, 30, 13, 18, 22, 20, 28, 13, 26, 12, 21, 32, 7, 26, 35, 21, 21, 18, 15, 20, 21, 10, 15, 34, 14, 19, 22, 26, 21, 22, 20, 11, 20, 13, 15, 35, 19, 10, 19, 20, 15, 28, 28, 23, 13, 24, 27, 19, 32, 31, 27, 24, 24, 24, 15, 25, 22, 11, 27, 23, 20, 30, 20, 26, 26, 22, 26, 17, 28, 20, 22, 24, 13, 29, 31, 23, 28, 24, 26, 25, 31, 25, 14, 36, 22, 25, 22, 16, 32, 26, 27, 27, 20, 18, 15, 16, 21, 17, 29, 27, 22, 23, 19, 41, 27, 11, 22, 9, 20, 25, 27, 13, 15, 38, 21, 24, 13, 27, 45, 21, 23, 25, 20, 29, 21, 25, 22, 19, 29, 24, 20, 17, 20, 26, 27, 25, 14, 28, 30, 23, 27, 31, 21, 31, 28, 30, 20, 17, 34, 19, 20, 35, 26, 34, 33, 27, 23, 19, 27, 23, 32, 32, 14, 31, 22, 13, 22, 12, 28, 33, 23, 25, 28, 18, 20, 29, 29, 20, 29, 30, 26, 24, 26, 26, 22, 32, 23, 30, 31, 24, 27, 25, 23, 31, 38, 49, 28, 17, 30, 39, 38, 30, 27, 31, 19, 36, 46, 27, 34, 24, 27, 30, 33, 32, 31, 26, 32, 29, 26, 25, 27, 33, 29, 31, 27, 24, 27, 20, 42, 26, 21, 19, 26, 37, 23, 35, 27, 25, 28, 35, 33, 31, 22, 28, 32, 41, 37, 31, 34, 26, 35, 27, 21, 34, 27, 26, 30, 27, 29, 41, 21, 19, 27, 27, 25, 37, 28, 23, 32, 31, 16, 29, 21, 27, 29, 30, 14, 25, 30, 29, 29, 30, 19, 31, 27, 32, 29, 26, 27, 18, 32, 18, 16, 33, 22, 32, 31, 24, 28, 25, 28, 27, 21, 36, 23, 24, 30, 21, 35, 25, 23, 31, 20, 25, 25, 13, 25, 26, 28, 19, 22, 33, 28, 34, 28, 31, 22, 20, 31, 23, 23, 23, 21, 38, 23, 21, 32, 27, 23, 25, 27, 32, 18, 44, 22, 21, 31, 18, 25, 21, 37, 22, 16, 23, 30, 28, 27, 18, 25, 39, 25, 28, 20, 31, 34, 21, 28, 19, 28, 20, 28, 15, 16, 37, 28, 30, 22, 20, 23, 21, 28, 26, 28, 35, 30, 27, 25, 19, 43, 20, 37, 28, 16, 22, 24, 23, 21, 18, 24, 27, 41, 28, 22, 21, 18, 20, 26, 21, 25, 21, 22, 31, 16, 23, 27, 28, 24, 19, 24, 46, 22, 29, 15, 29, 16, 26, 23, 21, 37, 29, 31, 21, 28, 26, 29, 27, 31, 15, 29, 32, 28, 31, 17, 36, 26, 27, 34, 19, 34, 26, 35, 23, 24, 26, 27, 24, 28, 15, 25, 21, 29, 31, 22, 34, 25, 22, 19, 6, 30, 31, 15, 27, 23, 23, 16, 26, 29, 26, 29, 23, 25, 28, 27, 41, 34, 19, 30, 27, 25, 26, 27, 25, 23, 28, 30, 21, 28, 18, 38, 30, 20, 34, 23, 42, 29, 30, 23, 20, 48, 28, 22, 35, 21, 32, 28, 31, 30, 19, 28, 35, 27, 30, 29, 36, 22, 20, 27, 25, 28, 21, 29, 32, 23, 30, 33, 32, 35, 20, 31, 26, 28, 30, 28, 38, 31, 34, 34, 25, 38, 30, 23, 13, 16, 28, 34, 30, 33, 27, 30, 29, 36, 31, 22, 21, 16, 26, 24, 20, 33, 19, 27, 27, 22, 28, 30, 25, 22, 20, 33, 38, 30, 21, 23, 36, 32, 31, 33, 27, 31, 28, 27, 32, 26, 37, 16, 28, 30, 30, 33, 31, 29, 27, 24, 29, 34, 30, 33, 26, 36, 34, 35, 21, 28, 36, 23, 32, 30, 29, 29, 30, 38, 30, 28, 45, 31, 29, 22, 20, 34, 19, 26, 30, 18, 33, 34, 30, 24, 23, 27, 23, 29, 31, 28, 37, 36, 29, 37, 26, 38, 27, 28, 33, 31, 30, 41, 33, 32, 30, 34, 27, 32, 28, 29, 40, 34, 37, 25, 29, 35, 27, 33, 26, 28, 44, 25, 44, 30, 13, 35, 38, 29, 29, 18, 23, 21, 26, 24, 21, 19, 30, 16, 27, 24, 28, 30, 22, 20, 27, 17, 22, 28, 27, 18, 42, 31, 8, 23, 15, 30, 34, 27, 29, 24, 38, 24, 31, 25, 22, 38, 29, 23, 28, 30, 16, 38, 23, 24, 32, 24, 22, 23, 29, 18, 29, 24, 27, 30, 22, 36, 18, 25, 28, 17, 37, 22, 29, 32, 22, 29, 23, 28, 33, 30, 40, 31, 29, 29, 14, 17, 18, 20, 26, 20, 18, 22, 27, 25, 18, 28, 17, 29, 16, 17, 28, 24, 27, 29, 17, 16, 17, 22, 34, 12, 23, 19, 26, 23, 29, 26, 22, 28, 22, 18, 22, 31, 23, 27, 23, 32, 24, 25, 29, 14, 13, 22, 30, 20, 18, 32, 18, 14, 25, 26, 18, 20, 24, 34, 18, 21, 12, 21, 25, 12, 25, 23, 31, 29, 17, 32, 26, 28, 26, 21, 26, 21, 39, 21, 18, 25, 22, 29, 32, 14, 26, 22, 31, 30, 13, 22, 31, 31, 13, 22, 27, 17, 23, 28, 5, 22, 19, 15, 28, 22, 13, 22, 24, 17, 20, 31, 12, 34, 25, 20, 36, 16, 19, 23, 20, 14, 24, 21, 25, 16, 23, 15, 25, 21, 11, 22, 28, 25, 27, 13, 25, 15, 12, 16, 18, 31, 26, 14, 24, 7, 27, 32, 19, 28, 16, 32, 24, 15, 19, 9, 25, 15, 24, 26, 12, 18, 20, 16, 25, 19, 25, 21, 31, 16, 12, 23, 18, 25, 25, 19, 20, 23, 11, 20, 13, 14, 20, 23, 19, 22, 24, 20, 24, 15, 20, 24, 25, 21, 20, 14, 19, 22, 27, 10, 17, 27, 19, 13, 20, 14, 28, 22, 26, 28, 19, 22, 22, 25, 25, 15, 20, 9, 19, 17, 19, 20, 17, 21, 30, 20, 20, 14, 20, 3, 18, 28, 19, 15, 14, 23, 32, 13, 35, 21, 31, 46, 20, 13, 30, 12, 26, 9, 14, 15, 17, 15, 13, 16, 24, 14, 14, 22, 25, 21, 16, 33, 20, 16, 19, 13, 23, 20, 19, 15, 20, 18, 18, 21, 26, 20, 20, 23, 27, 16, 12, 14, 26, 16, 14, 17, 22, 23, 17, 22, 12, 36, 20, 16, 20, 15, 26, 16, 12, 17, 19, 21, 25, 15, 27, 8, 21, 14, 27, 10, 4, 23, 32, 23, 27, 16, 26, 16, 20, 28, 6, 25, 19, 28, 26, 8, 21, 16, 19, 24, 19, 21, 24, 29, 15, 23, 13, 28, 20, 21, 18, 23, 20, 15, 24, 20, 21, 29, 27, 16, 8, 21, 26, 27, 12, 17, 21, 17, 12, 16, 13, 16, 20, 29, 14, 8, 39, 16, 12, 23, 14, 25, 16, 21, 19, 8, 20, 17, 14, 17, 12, 40, 19, 29, 26, 23, 22, 30, 30, 29, 20, 29, 14, 24, 28, 22, 35, 27, 33, 25, 13, 16, 13, 21, 19, 29, 33, 18, 16, 23, 25, 34, 19, 29, 30, 11, 33, 23, 26, 30, 14, 24, 35, 26, 20, 16, 32, 28, 28, 26, 7, 29, 21, 29, 21, 19, 29, 12, 27, 30, 16, 29, 34, 38, 23, 29, 27, 29, 21, 15, 27, 39, 22, 40, 23, 24, 28, 17, 27, 4, 26, 16, 31, 35, 24, 10, 20, 17, 21, 23, 12, 17, 30, 30, 28, 19, 24, 14, 29, 9, 18, 26, 17, 21, 31, 16, 5, 20, 24, 28, 11, 28, 20, 24, 14, 7, 25, 22, 25, 21, 19, 34, 9, 27, 25, 21, 21, 17, 21, 27, 12, 20, 17, 22, 27, 23, 26, 20, 30, 28, 19, 29, 27, 33, 19, 21, 40, 27, 19, 30, 13, 21, 25, 20, 36, 14, 28, 28, 35, 33, 24, 18, 19, 23, 27, 20, 36, 22, 31, 22, 19, 30, 19, 14, 24, 15, 18, 15, 26, 16, 16, 28, 24, 27, 21, 8, 28, 16, 24, 32, 17, 29, 20, 28, 31, 20, 24, 15, 4, 23, 12, 29, 18, 20, 32, 20, 26, 15, 17, 21, 12, 27, 20, 21, 27, 18, 19, 22, 28, 26, 26, 23, 26, 32, 19, 20, 36, 33, 31, 28, 17, 33, 26, 30, 37, 29, 32, 34, 22, 39, 24, 28, 28, 20, 30, 19, 19, 26, 29, 33, 21, 23, 25, 30, 30, 27, 27, 22, 31, 31, 23, 26, 36, 28, 27, 15, 25, 32, 30, 23, 19, 30, 20, 32, 29, 13, 27, 29, 32, 30, 12, 28, 25, 31, 20, 9, 32, 22, 36, 27, 17, 21, 18, 29, 33, 13, 17, 26, 30, 10, 12, 24, 26, 31, 25, 19, 26, 17, 26, 27, 18, 27, 24, 23, 26, 22, 21, 19, 19, 21, 16, 35, 20, 21, 19, 7, 35, 15, 19, 9, 20, 30, 18, 13, 26, 9, 28, 22, 37, 27, 18, 20, 27, 22, 20, 17, 19, 21, 25, 22, 15, 29, 20, 21, 36, 21, 21, 23, 33, 21, 18, 29, 25, 29, 33, 8, 20, 28, 24, 29, 13, 34, 22, 15, 20, 28, 25, 22, 26, 7, 15, 28, 31, 28, 30, 27, 28, 30, 18, 24, 18, 34, 22, 29, 33, 24, 26, 23, 26, 30, 27, 31, 33, 27, 32, 22, 38, 28, 34, 37, 17, 23, 26, 27, 38, 16, 15, 12, 21, 30, 18, 28, 28, 17, 21, 8, 31, 21, 26, 19, 23, 24, 20, 22, 13, 29, 38, 24, 22, 30, 30, 29, 33, 41, 22, 15, 34, 29, 32, 39, 37, 31, 23, 27, 37, 28, 37, 39, 34, 26, 21, 23, 22, 40, 38, 29, 29, 37, 48, 28, 32, 50, 40, 21, 20, 15, 33, 39, 43, 46, 28, 26, 29, 23, 27, 38, 43, 30, 28, 18, 21, 35, 32, 45, 29, 23, 23, 25, 47, 39, 40, 37, 32, 15, 21, 26, 41, 36, 34, 12, 23, 35, 33, 40, 44, 27, 26, 26, 28, 26, 38, 53, 37, 23, 22, 29, 38, 34, 46, 46, 13, 25, 22, 29, 36, 38, 40, 25, 40, 24, 33, 39, 43, 40, 22, 18, 22, 25, 32, 41, 38, 36, 29, 18, 33, 33, 65, 40, 32, 26, 29, 41, 38, 40, 41, 40, 30, 28, 28, 46, 37, 46, 44, 26, 25, 17, 38, 47, 43, 46, 22, 26, 29, 35, 43, 52, 44, 44, 23, 32, 34, 46, 55, 45, 24, 19, 30, 26, 43, 60, 44, 42, 34, 31, 40, 35, 54, 52, 45, 38, 36, 48, 38, 50, 57, 46, 46, 33, 39, 40, 55, 56, 55, 36, 36, 26, 64, 47, 48, 45, 38, 38, 34, 41, 53, 44, 56, 40, 23, 33, 39, 57, 63, 57, 55, 31, 42, 42, 43, 58, 47, 45, 41, 39, 39, 41, 61, 49, 47, 38, 34, 49, 57, 56, 69, 49, 45, 44, 44, 52, 61, 65, 48, 45, 41, 42, 60, 58, 53, 66, 50, 44, 36, 46, 63, 57, 70, 41, 40, 32, 46, 61, 61, 63, 55, 48, 36, 49, 55, 59, 61, 51, 45, 38, 55, 47, 54, 73, 48, 52, 40, 56, 46, 64, 63, 52, 57, 49, 53, 42, 62, 58, 53, 55, 57, 43, 67, 59, 53, 64, 54, 46, 41, 55, 64, 64, 53, 58, 44, 50, 61, 63, 63, 63, 70, 57, 51, 57, 60, 67, 54, 73, 63, 68, 36, 54, 77, 61, 61, 66, 44, 49, 68, 72, 68, 55, 64, 62, 52, 73, 70, 79, 63, 64, 50, 72, 78, 68, 75, 71, 48, 67, 69, 54, 75, 81, 83, 65, 71, 71, 53, 89, 84, 71, 68, 56, 82, 72, 65, 82, 61, 84, 67, 68, 75, 65, 85, 65, 68, 74, 71, 86, 76, 73, 88, 71, 78, 81, 75, 72, 81, 79, 80, 70, 84, 69, 84, 78, 76, 71, 63, 91, 85, 76, 73, 79, 68, 77, 81, 75, 67, 80, 84, 78, 76, 77, 91, 79, 75, 87, 68, 78, 79, 84, 76, 68, 85, 77, 79, 87, 74, 96, 84, 72, 75, 76, 80, 78, 94, 85, 72, 78, 79, 86, 80, 70, 86, 75, 76, 83, 79, 88, 89, 77, 86, 85, 73, 82, 84, 93, 77, 88, 81, 82, 84, 81, 86, 87, 91, 64, 72, 95, 84, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
In reply to this post by viruxx
discovered something while playing with this mode

here is the grayscale a4 preview (same than b/w a4 preview)

>>> dev.write(0x3,"\x03\x09\x01"); dev.read(0x85,100)
<<<array('B', [0])//scanner response

>>> dev.write(0x3,"\x03\x0D\x0B"); dev.read(0x85,100)
<<<array('B', [126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])//scanner response

>>> dev.write(0x3,"\x03\x0C\x11\x00\x00\x00\x01\x02\x05\xFF\x00\x00\x00\x00\xE8\x13\x68\x1B");
>>> dev.write(0x3,"\x03\x0B\x08"); dev.read(0x85,100)
<<<array('B', [0, 10, 180, 13, 244, 9, 180, 13]) //scanner response

>>> dev.write(0x3,"\x03\x08\x04\x00\x00\x00\x00\x08\x89\x00\x01"); //scanner give a 64000 data packet
 dev.write(0x3,"\x03\x0E\x04\x00\x00\x00\x00\xFA"); dev.read(0x85,100) //add a 64000 data packet

the \x03\x0E\x04\x00\x00\x00\x00\xFA sequence is executed 32 times

after that it send   \x03\x0E\x04\x00\x00\x00\x00\xBE and receive only 48640 data packet

then return to 32 times   \x03\x0E\x04\x00\x00\x00\x00\xFA 64000 data

until the end



Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
This post was updated on .
In reply to this post by viruxx
ok, lets resume all of this
i converted the python program in java, its more habitual to manipulate this language for me
i combined every modes, color, grayscale and bw, all in 75ppp resolution with 2 different size
*full plate a4+a little margin
*semi sized a5 manually resized in paintbrush scan
for the moment i really dont know how to interpret the 3 to 10 billions bytes i receive

actual results of the program:
motor do the travel, light goes on yellow for bw and grayscale, and more lightening blue light in color scan
it give datas, stop at the end in a4, stop at the middle in a5, and then, return at idle position
results sent and received were compared succesfully with windows xp original values

heres the work (values are converted in decimal for be more readable)

public class maine {static boolean continuer=true;
  private static DeviceHandle handle;  
  static boolean grayscalePreview=true, colorPreview=false, blackPreview=false, sizeA4 = false; //75 ppp quality

        public static void main(String[] args) {  
                getUsb();
               
                send(new byte[]{3,9,1});   read(handle,1  );//start signal return 0x00
                send(new byte[]{3,13,11}); read(handle,11  );//start signal return 0x7E 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
               
                if(sizeA4){
                        if(blackPreview || grayscalePreview)send(new byte[]{3,12,17,0,0,0,1,2,5,-1,0,0,0,0,-24,19,104,27});
                        if(colorPreview)    send(new byte[]{3,12,17,0,0,0,1,3,5,-1,0,0,0,0,-24,19,104,27});
                        send(new byte[]{3,11,8});  read(handle,8  );//confirmation return 0x00 0x0A 0xB4 0x0D 0xF4 0x09 0xB4 0x0D
                        if(blackPreview || grayscalePreview)send(new byte[]{3,8,4,0,0,0,0,8,-119,0,1  });
                        if(colorPreview)    send(new byte[]{3,8,4,0,0,0,0,24,-101,1,1  });
                }
                if(!sizeA4){ //A5 semi height
                        if(blackPreview )send(new byte[]{3,12,17,0,0,0,1,2,5,-1,0,0,0,0,-24,19,-56,13});    
                        if(grayscalePreview )send(new byte[]{3,12,17,0,0,0,1,2,5,-1,0,0,0,0,-24,19,72,14});
                        if(colorPreview)    send(new byte[]{3,12,17,0,0,0,1,3,5,-1,0,0,0,0,-24,19,104,13});
                        send(new byte[]{3,11,8});  read(handle,8  );//confirmation return 0x00 0x0A 0xCC 0x06 0xF4 0x09 0xCC 0x06
                        if(blackPreview)send(new byte[]{3,8,4,0,0,0,0,-24,68,0,1  });
                        if(grayscalePreview)send(new byte[]{3,8,4,0,0,0,0,104,71,0,1  });
                        if(colorPreview)    send(new byte[]{3,8,4,0,0,0,0,-24,(byte) 203,0,1  });
                }
  int operation = 1;
                 while(continuer){
                         ByteBuffer readed =null;
                 
                         if(operation %32 !=0 ){ System.out.println(operation+" normal operation number "+operation);
                                 if(blackPreview || grayscalePreview)send(new byte[]{3,14,4,0,0,0,0,-6  });
                                 if(colorPreview ) send(new byte[]{3,14,4,0,0,0,0,-16  });
                                 if(blackPreview || grayscalePreview)readed = read(handle,64000);
                                 if(colorPreview  ) readed = read(handle,61440);
                         }
                         else{System.out.println("strange signal every 32 operation");
                          if(sizeA4 && blackPreview)send(new byte[]{3,14,4,0,0,0,0,-36 });
                          if(!sizeA4 && blackPreview)send(new byte[]{3,14,4,0,0,0,0,(byte) 220 });
                          if(grayscalePreview && sizeA4)send(new byte[]{3,14,4,0,0,0,0,-66  });
                          if(grayscalePreview && !sizeA4)send(new byte[]{3,14,4,0,0,0,0,(byte) 190  });
                          if(colorPreview) send(new byte[]{3,14,4,0,0,0,0,60  });// 60 not change in a5 sized
                          if(blackPreview)readed = read(handle,56320);
                          if(grayscalePreview)readed = read(handle,48640);
                          if(colorPreview) readed = read(handle,15360);
                         }
                         
                         //windows driver send a strange end signal when he know (i dunno how)
                         //that the next buffer will not be full and be the last.  
                         //i didnt find in any usblib documentation how to get the _urb_header with the
                         //size of the next packet, i manually put the operation number
                         if( sizeA4 && grayscalePreview && operation==141||!sizeA4 && grayscalePreview && operation==73){
                                 if(sizeA4)send(new byte[]{3,14,4,0,0,0,0,70});
                                 if(sizeA4)read(handle,17920  );
                                 if(!sizeA4)send(new byte[]{3,14,4,0,0,0,0,(byte) 150});
                                 if(!sizeA4)read(handle,38400  );
                                 continuer=false;  
                         }//if the end signal is not sent in bw and grayscale mode, it will continue to receive
                         //full 0x00 64000 sized buffers during 60s, motor go back at idle position but printer busy during the 60s. In color reading it goes on timeout, and motor return at idle position, and printer no more busy
                         if(sizeA4 && blackPreview && operation==140 || !sizeA4 && blackPreview && operation==70){
                                 if(sizeA4)send(new byte[]{3,14,4,0,0,0,0,-56});
                                 if(!sizeA4)send(new byte[]{3,14,4,0,0,0,0,(byte) 200});
                                 read(handle,51200  ); //last packet size not changed with the A5 size Oo
                                 continuer=false;
                         }
                         if(sizeA4 &&colorPreview && operation==448){//strange thing here, if i stop at >449, motor go back at idle position,
                                 send(new byte[]{3,14,4,0,0,0,0,120});//printer is ready but script goes on timeout at line "readed = read(handle,61440);"
                                 read(handle,30720  ); //if i stop it at <449 i achieve the end signal reception, motor goes at idle position, but the
                                 continuer=false; //printer stay busy during 60s in "pc scanning" after the end
                         }
                         if(!sizeA4 &&colorPreview && operation==219)
                                 continuer=false;//i had no end signal in this semi sized A5 color scan, last buffer = 61440 too
                         
                         operation++;
                         
                }  
                send(new byte[]{3,9,1}); read(handle,1  ); //end signal, return 0x00
                LibUsb.releaseInterface(handle, 0);
                LibUsb.close(handle);
 
        }
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
ok today i worked with the data, i added this in the loop

  try { FileChannel channel = new FileOutputStream(new File("out.xml"), true).getChannel(); //true = append data
  channel.write(readed);
                                                         channel.close(); } catch (Exception e) {e.printStackTrace(); }

with grayscale data i was able to have this


using this

try {
        FileInputStream fIn = new FileInputStream("out.xml");
        FileChannel fChan = fIn.getChannel();
        long fSize = fChan.size();
         ByteBuffer buffer = ByteBuffer.allocate((int) fSize);
         fChan.read(buffer);
         buffer.rewind();  
    DataBufferByte dbb = new DataBufferByte(buffer.array(), buffer.capacity());
             WritableRaster raster = Raster.createInterleavedRaster(dbb, 2560, 3501, 2560, 1, new int[]{0}, (Point) null); //i found w=2560 with a little play in gimp, opening a raw file, indexed rgb selected
              //here size / 2560 = 3501
             ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
             
             BufferedImage image = new BufferedImage(cm, raster, true, null);
             ImageIO.write(image, "png", new File("imagegray.png"));
             fIn.close();
         } catch (IOException ex) {  ex.printStackTrace();  }

________________________________________________________________________
for a color scan (size / 2560 = 10500) i have problem

trying this

   raster = Raster.createInterleavedRaster(dbb, 2560, 3500, 2560*3, 3, new int[]{2,1,0}, (Point) null);
   cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);

gave me this

Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
This post was updated on .
In reply to this post by viruxx
Path path = Paths.get("color.data");//raw data
    byte[] buffer = Files.readAllBytes(path);
    int passed=0;
    int width = 2560;
    int height = 3500;
    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    for(int i = 0 ; i<buffer.length-(width*3) ; i++ ){//loop bytes one by one
    if(i%width == 0){i+=width*2;passed+=width*2;}//if 1 width line passed jump 2 lines
    int r = buffer[i]& 0xFF;//first byte
    int g = buffer[i+width]& 0xFF;//second byte 1 line after
    int b = buffer[i+width+width]& 0xFF;//third byte 2 lines after
    Color color = new Color( g,b,r );//not rgb not rbg not grb not bgr not brg but GBR xD
    img.setRGB((i-passed)%width, (i-passed)/width, color.getRGB()); //put pixel at good place
    }  
    ImageIO.write(img, "png", new File("realcolor.png")); //finally a real readable file <3
    } catch (IOException ex) {  ex.printStackTrace();  }

//finally i got it , thanx to the one who helped me in webchat
//its a 1 line by color storage in GBR order

//here you got the first color scan of an aficio sp100su in linux :D

<nabble_img src="imagefinale3.jpg" border="0"/>

 
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
This post was updated on .
In reply to this post by viruxx
ok the work is finished
i cleaned all the code, and removed things that was not usefull

for be short, this scanner support only 2 quality 300 dpi and 600 dpi
with 2 modes, color or grayscale, all the rest is software controlled

i sniffed the usb informations when resizing the scan area after a preview
totally useless : if we choose just a little area at the end of the A4 in 600 dpi,
the motor is going slow on the whole page, so i implemented nothing about it

i give you my driver in java :
package me.virux;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
import org.usb4java.BufferUtils;
import org.usb4java.Context;
import org.usb4java.DeviceHandle;
import org.usb4java.LibUsb;

public class AficioSP100su {
       
        //variables can be changed by soft // default 300dpi, highquality = 600dpi
  static DeviceHandle usb; static int height = 3510; //height can be less if we want just a part of A4
  static String imageType = "png", filename="sexyFileName"; //b/w scan can be soft controlled only
  static boolean color=false, black=false, cancel=false, highQuality=false;// here we got a 300dpi grayscale
   
  static final short vendor = (short)0x05ca, product = (short)0x042c;//constants values
  static final byte urb_to = (byte) 0x03, urb_from = (byte) 0x85;
 
        public static void main(String[] args) throws IOException {  
                int width = 2560, packet = 61440;
                if(highQuality){ width *= 2; height *= 2; }  
                int bytesToRead = width * height, totalBytesRead = 0;
                if(color) bytesToRead *= 3;
                 
                Context c = new Context();//start usb
                LibUsb.init(c);
                usb = LibUsb.openDeviceWithVidPid(c, vendor, product);
                LibUsb.claimInterface(usb, 0);
                 
                send(new byte[]{0x03,0x09,0x01});    //start urb procedure
                read(1);
                send(new byte[]{0x03,0x0d,0x0b});
                read(11);
                byte[] sequence = new byte[]{0x03,0x0c,0x11,0,0,0,0x01,0x02,0x05,0xffffffff,0,0,0,0,0xffffffec,0x13,0x6c,0x1b};
                if(highQuality)
                        sequence[6]=0x02;
                if(color)
                        sequence[7]=0x03;
                send(sequence);
                send(new byte[]{0x03,0x0b,0x08});
                read(8);
                send(new byte[]{0x03,0x08,0x04,0,0,0,0,0x50,0x6d,0x06,0x01});
                 
                //#######main loop
                ByteBuffer buffer = ByteBuffer.allocateDirect(bytesToRead);
  boolean loop = true;
  while(loop){
  if(cancel)//soft can cancel the scan at every moment
  send(new byte[]{0x03,0x0a});  
  send(new byte[]{0x03, 0x0E, 0x04, 0,0,0,0,(byte) (packet/256) }); //give me next packet pls
                           
  buffer.put( read(packet) );
  totalBytesRead+=packet;
                         
  if(totalBytesRead + packet >  bytesToRead)
  packet = bytesToRead - totalBytesRead;
 
  if(totalBytesRead >= bytesToRead || packet == 0)
  loop = false;
  }//end of main loop
                 
                 send(new byte[]{0x03,0x0a}); //send cancel
                 send(new byte[]{0x03,0x09,0x01}); //send end
                 read(1); //dont forget response
               
                 //no need usb anymore
                 LibUsb.releaseInterface(usb, 0);
                 LibUsb.close(usb);
               
                 
                //########## data interpretation
                int passed = 0; BufferedImage img = null;

                if(color){ //storage of aficio sp100 is 1 line = 1 color channel
                        img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
                       
                        for(int i = 0 ; i < totalBytesRead - (width * 3) ; i++ ){//loop the buffer until last line -2
                                if(i % width == 0){ //if 1 complete width/line readed, jump over 2 lines/width
                                        i += width * 2 ;
                                        passed += width * 2 ;
                                }
                                int r = buffer.get(i) & 0xFF;//first color is at current position
                                int g = buffer.get(i + width) & 0xFF;//second color is at next line/width
                                int b = buffer.get(i + width + width) & 0xFF;//3rd color is 2 lines after
                                Color col = new Color( g,b,r ); //mix the 3 bytes in THIS order /!\
                                img.setRGB( (i-passed) % width, (i-passed) / width, col.getRGB()); //place pixel using line position
                        }  
                }else{
                        img = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY);
                       
                        if(black)//if black selected, software push it here
                                img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
                       
                        for(int i = 0 ; i < totalBytesRead ; i++ ) {
                                int gray = buffer.get(i) & 0xFF;
                                img.setRGB(i % width, i / width, new Color(gray, gray, gray).getRGB() );
                        }
                }
                ImageIO.write(img, imageType, new File(filename+"."+imageType.replaceAll("jpeg", "jpg")));  
        }//end of main program
       
        //###########################################################################
        static void send(byte[] text) {  
                ByteBuffer buffer = ByteBuffer.allocateDirect( 64 );
                buffer.put(text);  
                LibUsb.bulkTransfer(usb, urb_to, buffer, IntBuffer.allocate(3), 20000);
        }
       
        //###########################################################################
        static ByteBuffer read(int size) {
                ByteBuffer buffer = BufferUtils.allocateByteBuffer(size).order( ByteOrder.LITTLE_ENDIAN);
        LibUsb.bulkTransfer(usb, urb_from, buffer, IntBuffer.allocate(3), 20000);
        return buffer;
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: add support for ricoh aficio sp100su

viruxx
This post has NOT been accepted by the mailing list yet.
This post was updated on .
In reply to this post by viruxx
//with an GUI it's better <3
viruxx wrote
package me.virux;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.usb4java.BufferUtils;
import org.usb4java.Context;
import org.usb4java.DeviceHandle;
import org.usb4java.LibUsb;

public class AficioSP100su {
       
        static File record;static JFrame frame = new JFrame("Julietta scanner");
         static JCheckBox boxblack = new JCheckBox("pure black"),
                         boxquality = new JCheckBox("hi quality"),
                         boxcolor = new JCheckBox("color"), boxjpeg = new JCheckBox("jpeg");
         static JProgressBar bar = new JProgressBar();
         static JButton scan = new JButton("scan");
  static DeviceHandle usb;  
  static boolean filechoosed = false,
  cancel=false ;
  static JFileChooser chooser = new JFileChooser();
  static JTextArea textarea = new JTextArea("Welcome to Julietta Scanner");
  static JTextField height = new JTextField("3510");
  static JLabel label = new JLabel("height:");
  static JPanel chooserpane = new JPanel();
 
 
        public static void main(String[] args) throws IOException {  
               
               
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
       
        ActionListener listener = new ActionListener(){
                        @Override public void actionPerformed(ActionEvent button) {
                                if(button.getSource().equals(boxcolor) && boxcolor.isSelected()==true)
                                        boxblack.setSelected(false);
                                if(button.getSource().equals(boxblack) && boxblack.isSelected()==true)
                                        boxcolor.setSelected(false);
                                if(button.getSource().equals(chooser) ){
                                         if(button.getSource().toString().contains("APPROVE_OPTION")){
                                                filechoosed=true;
      textarea.setText(chooser.getSelectedFile().getAbsolutePath());
                                         }
                                         else
                                                cancel=true;
                                     chooserpane.remove(chooser);
                                     frame.repaint();frame.revalidate();
                                }
                                if(button.getSource().equals(scan)){
                                        enableChooser();

                                       
                                        new Thread(){public void run(){
                                                                scan.setEnabled(false);
                                                                try {
                                                                        scan(Integer.parseInt(height.getText()));
                                                                } catch (Exception e) {scan.setEnabled(true);chooserpane.remove(chooser);frame.repaint();frame.revalidate();
                                                                        textarea.setText("error permission or no aficio sp100su detected "+e.getMessage());}  
                                                        }}.start();
                                }
                                 
                        }

                       
        };
                boxcolor.addActionListener(listener);  chooser.addActionListener(listener);
                boxblack.addActionListener(listener);  scan.addActionListener(listener);
               
                chooserpane.setPreferredSize(new Dimension(510,320));
        frame.getContentPane().add(chooserpane, BorderLayout.PAGE_START);
        frame.getContentPane().add(scan, BorderLayout.LINE_START);
        frame.getContentPane().add(getBoxesPanel(), BorderLayout.LINE_END);
        frame.getContentPane().add(getBottomPanel(), BorderLayout.PAGE_END);
        frame.pack();
        frame.setVisible(true);
   }//end of main program
       
   static void enableChooser() {
           textarea.setText("file ?");
           String path = chooser.getCurrentDirectory().getAbsolutePath();
                chooser.setSelectedFile(new File(path+"/sexyFileName "+getTime() ));
                chooser.setFileFilter(null);
                chooserpane.add(chooser);
   }
       
       
        private static String getTime() {
                Date date = new Date();
                int min = date .getMinutes();
                int sec = date.getSeconds();
                return min+"-"+sec;
        }

        static JPanel getBoxesPanel(){
          JPanel boxarea = new JPanel(); GridLayout layout = new GridLayout();
                layout.setColumns(1); layout.setRows(4); boxarea.setLayout(layout);
                boxjpeg.setSelected(true); boxcolor.setSelected(true); boxquality.setSelected(true);
             
            boxarea.add(boxcolor); boxarea.add(boxquality);
            boxarea.add(boxblack); boxarea.add(boxjpeg);
            boxarea.add(label); boxarea.add(height);
            return boxarea;
        }
       
        static JPanel getBottomPanel(){
                JPanel panel = new JPanel(); GridLayout layout = new GridLayout();
                layout.setColumns(1); layout.setRows(2); panel.setLayout(layout);
                panel.add(textarea); panel.add(bar);
                return panel;
        }
       
       
       
        static void scan(int height) throws Exception{
                filechoosed = false;
                cancel=false;
                int width = 2560, packet = 61440;
                if(boxquality.isSelected()){ width *= 2; height *= 2; }  
                int bytesToRead = width * height, totalBytesRead = 0;
                if(boxcolor.isSelected()) bytesToRead *= 3;
                bar.setMaximum(bytesToRead);bar.setValue(0);
                Context c = new Context();//start usb
                LibUsb.init(c);
                usb = LibUsb.openDeviceWithVidPid(c, (short)0x05ca, (short)0x042c);
                LibUsb.claimInterface(usb, 0);
                 
                send(new byte[]{0x03,0x09,0x01});    //start urb procedure
                read(1);
                send(new byte[]{0x03,0x0d,0x0b});
                read(11);
                byte[] sequence = new byte[]{0x03,0x0c,0x11,0,0,0,0x01,0x02,0x05,0xffffffff,0,0,0,0,0xffffffec,0x13,0x6c,0x1b};
                if(boxquality.isSelected())
                        sequence[6]=0x02;
                if(boxcolor.isSelected())
                        sequence[7]=0x03;
                send(sequence);
                send(new byte[]{0x03,0x0b,0x08});
                read(8);
                send(new byte[]{0x03,0x08,0x04,0,0,0,0,0x50,0x6d,0x06,0x01});
                 
                //#######main loop
                ByteBuffer buffer = ByteBuffer.allocateDirect(bytesToRead);
  boolean loop = true;
  while(loop){ bar.setValue(totalBytesRead);
 
  send(new byte[]{0x03, 0x0E, 0x04, 0,0,0,0,(byte) (packet/256) }); //give me next packet pls
                           
  buffer.put( read(packet) );
  totalBytesRead+=packet;
                         
  if(totalBytesRead + packet >  bytesToRead)
  packet = bytesToRead - totalBytesRead;
 
  if(totalBytesRead  >= bytesToRead || packet == 0 || cancel)
  loop = false;
  }//end of main loop
                 
                 send(new byte[]{0x03,0x0a}); //send cancel
                 send(new byte[]{0x03,0x09,0x01}); //send end
                 read(1); //dont forget response
               
                 //no need usb anymore
                 LibUsb.releaseInterface(usb, 0);
                 LibUsb.close(usb);
                 scan.setEnabled(true);
                 while(!filechoosed && !cancel)
                                 Thread.sleep(1000);
                 chooserpane.remove(chooser); frame.repaint();frame.revalidate();
                //########## data interpretation
                int passed = 0; BufferedImage img = null;
                bar.setMaximum(totalBytesRead);bar.setValue(0);
                if(boxcolor.isSelected()){ //storage of aficio sp100 is 1 line = 1 color channel
                        img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
                       
                        for(int i = 0 ; i < totalBytesRead - (width * 3) ; i++ ){//loop the buffer until last line -2
                                if(i % width == 0){ //if 1 complete width/line readed, jump over 2 lines/width
                                        i += width * 2 ;
                                        passed += width * 2 ;
                                }bar.setValue(i);
                                if(cancel )return;
                                int r = buffer.get(i) & 0xFF;//first color is at current position
                                int g = buffer.get(i + width) & 0xFF;//second color is at next line/width
                                int b = buffer.get(i + width + width) & 0xFF;//3rd color is 2 lines after
                                Color col = new Color( g,b,r ); //mix the 3 bytes in THIS order /!\
                                img.setRGB( (i-passed) % width, (i-passed) / width, col.getRGB()); //place pixel using line position
                        }  
                }else{
                        img = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY);
                       
                        if(boxblack.isSelected())//if black selected, software push it here
                                img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
                       
                        for(int i = 0 ; i < totalBytesRead ; i++ ) {bar.setValue(i);if(cancel )return;
                                int gray = buffer.get(i) & 0xFF;
                                img.setRGB(i % width, i / width, new Color(gray, gray, gray).getRGB() );
                        }
                }
                if(cancel )return;
                 String path = textarea.getText();
                if(boxjpeg.isSelected())
                        ImageIO.write(img, "jpeg", new File(path + ".jpg"));  
                else
                        ImageIO.write(img, "png", new File(path + ".png"));  
               
        }
        //###########################################################################
        static void send(byte[] text) {  
                ByteBuffer buffer = ByteBuffer.allocateDirect( 64 );
                buffer.put(text);  
                LibUsb.bulkTransfer(usb, (byte) 0x03, buffer, IntBuffer.allocate(3), 20000);
                 
        }
       
        //###########################################################################
        static ByteBuffer read(int size) {
                ByteBuffer buffer = BufferUtils.allocateByteBuffer(size).order( ByteOrder.LITTLE_ENDIAN);
        LibUsb.bulkTransfer(usb, (byte) 0x85, buffer, IntBuffer.allocate(3), 20000);
        return buffer;
    }
}