Skip to content

Commit

Permalink
Integrate dellscan.py into repository
Browse files Browse the repository at this point in the history
  • Loading branch information
2xB committed Oct 25, 2018
1 parent 67aed7b commit 4ac759c
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Dellscan
## Overview
Scans files from device "Dell S2825cdn". Provides a simple command line interface.
```
$ dellscan --help
Scan document from Dell S2825cdn device.
Usage: dellscan file [--greyscale] [-gs] [FILE]
Filenames cannot start with '-'.
```
## Installation:
```
$ sudo cp dellscan.py /usr/bin/dellscan
$ sudo chmod +x /usr/bin/dellscan
```
172 changes: 172 additions & 0 deletions dellscan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/usr/bin/python3

import sys
import usb.core
import usb.util
import numpy as np
import math

from PIL import Image

def read_assert(expected, dev, timeout = None):
ans = dev.read(0x82, len(bytearray(expected)),timeout)
if ans != bytearray(expected):
print("Expected", bytearray(expected).hex(), ", got", bytearray(ans).hex())

def to_int(bytearr):
return int.from_bytes(bytearr, byteorder='big')

def to_byte(value,length=2):
return value.to_bytes(length,byteorder='big')

def rgbs(l):
return np.array(list(bytearray(l)))

def scan(greyscale=False):
# Init device connection
dev = usb.core.find(idVendor=0x413c, idProduct=0x5910)
if dev is None:
raise ValueError('Device not found')
reattach = False
if dev.is_kernel_driver_active(1):
reattach = True
dev.detach_kernel_driver(1)
dev.reset()
dev.set_configuration()

# Init device connection
dev.write(0x01,bytearray([0,0x5a,0,0,0,0,0,0x04,0x20,0,0,0]))
ans = dev.read(0x82,64)

part = bytearray([0x15, 0x4e, 0xb2, 0xdd, 0x0e, 0xe2, 0x55, 0x56])
command = bytearray([0x00, 0x16, 0x00, 0x01, 0x00, 0x00, 0x01, 0x10, 0xec, 0xfe, 0x19, \
0x99, 0x13, 0x7d, 0xe5, 0xff, 0x0e, 0xff, 0xe2, 0x5f, 0x9c, 0xbb, \
0x00, 0x24])\
+ 2*part + bytearray([0xc6, 0x0b, 0xa0, 0xb9, 0xb7, 0x5a, 0x3a, 0x29, 0x74,\
0xcb, 0x94, 0x00, 0xe4, 0x52, 0x68, 0x4c, 0x0f, 0xd7,\
0x29, 0x90, 0x73, 0x72, 0xf2, 0x00])\
+ 2*part + bytearray([0x4c, 0x88, 0xea, 0x31, 0xae, 0xf8, 0x12, 0xb1, 0x39,\
0x99, 0x42, 0x28, 0xc0, 0xc1, 0xa3, 0xa8])\
+ 23*part
dev.write(0x01,command)

# Wait until init is ready
ans2 = dev.read(0x82, 8, timeout=100000)

current = bytearray([bytearray(ans2)[0]])
expected = current + bytearray([0x16, 0, 0x01, 0,0,0,0])
if ans2 != expected:
print("Expected", expected.hex(), ", got", ans.hex())

dev.write(0x01, current + bytearray([0x07, 0,0,0,0,0, 0x04, 0,0,0,0]))
read_assert(current + bytearray([0x07,0,0x01,0,0,0,0]), dev)

size = 4
byte_resolution = bytearray(to_byte(300))
if not greyscale:
byte_farbe = bytearray(to_byte(0x5,1))
else:
byte_farbe = bytearray(to_byte(0x2,1))
if size == 5: # Din A5
byte_width = bytearray(to_byte(0x1b50))
byte_height = bytearray(to_byte(0x26c0))
else: # Din A4
height = 3506
width = 2496
byte_width = bytearray(to_byte(0x26c0))
byte_height = bytearray(to_byte(0x36cc))
byte_realwidth = bytearray(to_byte(math.ceil(to_int(byte_width)/128)*128))

# Here indention could be added
byte_indention = bytearray(to_byte(0,1))

# Scan command
dev.write(0x01, current + bytearray([0x24, 0,0,0,0,0, 0x30, 0,0])+2*byte_resolution+bytearray(5)+byte_indention+bytearray(6)\
+byte_realwidth+bytearray(2)+byte_height+bytearray(2)+byte_farbe+bytearray([0x08,0,0x31])+bytearray(5)\
+byte_indention+bytearray(6)+byte_width+bytearray(2)+byte_height)
read_assert(current + bytearray([0x24,0,0x01,0,0,0,0]), dev)

dev.write(0x01, current + bytearray([0x1b, 0,0,0,0,0,0]))
read_assert(current + bytearray([0x1b,0,0x01,0,0,0,0]), dev)

dev.write(0x01, current + bytearray([0xc2, 0,0,0,0,0,0]))
if greyscale:
read_assert(current + bytearray([0xc2,0,0x02,0,0,0,0x0c,0x02,0,0,0,\
0x00,0x85,0x91,0x40,\
0x00,0x85,0x91,0x40]),dev, 100000)
else:
read_assert(current + bytearray([0xc2,0,0x02,0,0,0,0x0c,0x05,0,0,0,\
0x01,0x90,0xb3,0xc0,\
0x01,0x90,0xb3,0xc0]),dev, 100000)

scan = bytearray()

if greyscale:
scanamount = 33
lastcommand_end = bytearray([0x01,0x91,0x40])
readlast2 = 101888
readlast3 = 328
else:
scanamount = 100
lastcommand_end = bytearray([0,0xb3,0xc0])
readlast2 = 45056
readlast3 = 456


for i in range(0,scanamount):
dev.write(0x01, current + bytearray([0x28, 0,0,0,0,0, 0x04,0,0x04,0,0]))
part1 = dev.read(0x82,512)
part2 = dev.read(0x82,261632)
part3 = dev.read(0x82,8)
scan += part1[8:]+part2+part3

dev.write(0x01, current + bytearray([0x28, 0,0,0,0,0, 0x04,0])+lastcommand_end)
part1 = dev.read(0x82,512)
part2 = dev.read(0x82,readlast2)
part3 = dev.read(0x82,readlast3)
scan += part1[8:]+part2+part3

dev.write(0x01, current + bytearray([0x07, 0,0,0,0,0, 0x04, 0, 0, 0, 0]))
read_assert(current + bytearray([0x07,0,0x01,0,0,0,0]), dev)

dev.write(0x01, current + bytearray([0x17, 0,0,0,0,0,0]))
read_assert(current + bytearray([0x17,0,0x01,0,0,0,0]), dev, 100*1000)

usb.util.dispose_resources(dev)
if reattach:
dev.attach_kernel_driver(1)

colors = rgbs(scan)

if not greyscale:
realcolors = np.reshape(colors[0:3*height*width],(height,width,3))
else:
realcolors = np.reshape(colors[0:height*width],(height,width))

return realcolors

def save_array_as_img(realcolors, name):
im = Image.fromarray(np.uint8(realcolors))
im.save(name)

if __name__ == "__main__":
args = sys.argv[1:]
greyscale = False
filename = ""
if len(args) == 2 and (args[0] == "--greyscale" or args[0] == "-gs"):
greyscale = True
filename = args[1]
elif len(args) == 2 and (args[1] == "--greyscale" or args[1] == "-gs"):
greyscale = True
filename = args[0]
elif len(args) == 1:
filename = args[0]

if filename == "" or filename[0] == '-':
print("Scan document from Dell S2825cdn device.\n" + \
"Usage: dellscan file [--greyscale] [-gs] [FILE]\n"+\
"Filenames cannot start with '-'.")
else:
arr= scan(greyscale)
save_array_as_img(arr, filename)

0 comments on commit 4ac759c

Please sign in to comment.