libcx320 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +3 -0
- data/lib/libcx320/c.rb +41 -0
- data/lib/libcx320/cx320.rb +422 -0
- data/lib/libcx320/device_dll.rb +130 -0
- data/lib/libcx320/device_simu.rb +132 -0
- data/lib/libcx320/device_usb.rb +220 -0
- data/lib/libcx320/error_handling.rb +129 -0
- data/lib/libcx320/version.rb +3 -0
- data/lib/libcx320.rb +9 -0
- data/libcx320.gemspec +23 -0
- data.tar.gz.sig +2 -0
- metadata +107 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c3547e9bba3f0346e0343c36dc511ff05d0cc5e244e6dc949be37b008d02e5b0
|
|
4
|
+
data.tar.gz: 4720512b76668f1ef5bb2d4fb80faf9e534378f7ba24b9e1b53e607e10bd1a55
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 873e3f5201b0bbf394a495531762482ed9b199076f2d4f1eb4895407cefc811b5c9851e032822016e4c4c58ea643ef5fcd239efd0a672316e41131cd7472a293
|
|
7
|
+
data.tar.gz: 3f72f2761dcfac9803a37f92a8986fce7e3d5607c1c177f09b23c2237eb3eee1f2032416db2b1f5569bf0ad09f7aa89e86225de3c8e3901d45e36532e05abf55
|
checksums.yaml.gz.sig
ADDED
|
Binary file
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 Holger Arndt
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Libcx320
|
|
2
|
+
|
|
3
|
+
Driver for Retransfer Printer CX-320.
|
|
4
|
+
Usable per PCP05CT.DLL on Windows or per direct LIBUSB access on any operating system.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Add this line to your application's Gemfile:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'libcx320'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And then execute:
|
|
15
|
+
|
|
16
|
+
$ bundle
|
|
17
|
+
|
|
18
|
+
Or install it yourself as:
|
|
19
|
+
|
|
20
|
+
$ gem install libcx320
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
TODO: Write usage instructions here
|
|
25
|
+
|
|
26
|
+
## Contributing
|
|
27
|
+
|
|
28
|
+
1. Fork it ( https://github.com/larskanis/libcx320 )
|
|
29
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
30
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
31
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
32
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/libcx320/c.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
module LibCX320
|
|
4
|
+
module C
|
|
5
|
+
extend FFI::Library
|
|
6
|
+
|
|
7
|
+
ffi_lib 'PCP05CT.DLL'
|
|
8
|
+
|
|
9
|
+
# Get Handle
|
|
10
|
+
attach_function :CXCMD_ScanCX320, [:pointer, :pointer], :int
|
|
11
|
+
attach_function :CXCMD_ScanCX320Next, [:pointer, :pointer], :int
|
|
12
|
+
|
|
13
|
+
# Checks
|
|
14
|
+
attach_function :CXCMD_CheckIfConnected, [:pointer, :pointer], :bool
|
|
15
|
+
attach_function :CXCMD_TestUnitReady, [:int, :int], :int
|
|
16
|
+
|
|
17
|
+
# Print & CardControl
|
|
18
|
+
attach_function :CXCMD_ReadPosition, [:int, :int, :pointer], :int
|
|
19
|
+
attach_function :CXCMD_ImageOut, [:int, :int, :pointer, :int, :int, :int], :int
|
|
20
|
+
attach_function :CXCMD_DefineLUT, [:int, :int, :int, :int, :pointer], :int
|
|
21
|
+
attach_function :CXCMD_Print, [:int, :int, :int, :int, :int], :int
|
|
22
|
+
attach_function :CXCMD_LoadCard, [:int, :int, :int, :int, :int, :int], :int
|
|
23
|
+
attach_function :CXCMD_MoveCard, [:int, :int, :int, :int, :int, :int], :int
|
|
24
|
+
attach_function :CXCMD_RetransferAndEject, [:int, :int, :int], :int
|
|
25
|
+
attach_function :CXCMD_RetransferAndTurn, [:int, :int, :int], :int
|
|
26
|
+
|
|
27
|
+
# MS Encoding
|
|
28
|
+
attach_function :CXCMD_WriteMagData, [:int, :int, :pointer, :int, :int], :int
|
|
29
|
+
attach_function :CXCMD_ReadMagData, [:int, :int, :pointer, :pointer, :int], :int
|
|
30
|
+
attach_function :CXCMD_ICControl, [:int, :int, :int, :int], :int
|
|
31
|
+
|
|
32
|
+
# Reset
|
|
33
|
+
attach_function :CXCMD_RezeroUnit, [:int, :int], :int
|
|
34
|
+
|
|
35
|
+
# Infos & Settings
|
|
36
|
+
attach_function :CXCMD_ModeSense, [:int, :int, :int, :pointer], :int
|
|
37
|
+
attach_function :CXCMD_ModeSelect, [:int, :int, :int, :pointer], :int
|
|
38
|
+
attach_function :CXCMD_LogSense, [:int, :int, :int, :pointer], :int
|
|
39
|
+
attach_function :CXCMD_LogSelect, [:int, :int], :int
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
|
|
2
|
+
module LibCX320
|
|
3
|
+
class CX320
|
|
4
|
+
attr_reader :dev
|
|
5
|
+
|
|
6
|
+
def initialize(dev)
|
|
7
|
+
@dev = dev
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.devices(dev_type)
|
|
11
|
+
dev_type.devices.map do |dev|
|
|
12
|
+
self.new(dev)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def close
|
|
17
|
+
@dev.close if @dev
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def ready?
|
|
21
|
+
@dev.ready?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def rezero_unit
|
|
25
|
+
@dev.rezero_unit
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get_current_card_position
|
|
29
|
+
resp = @dev.get_current_card_position
|
|
30
|
+
|
|
31
|
+
# PU (Position Unknown) - Byte 0 Bit 3
|
|
32
|
+
# 0: The card is in the printer unit.
|
|
33
|
+
# 1: No card in the printer unit
|
|
34
|
+
#
|
|
35
|
+
# Note: Printer reports PU = 1 even if any card is in the card hopper. Printer generates
|
|
36
|
+
# Check Condition if the card is being transported.
|
|
37
|
+
#
|
|
38
|
+
# Byte 7
|
|
39
|
+
# Position: Card position in the printer unit.
|
|
40
|
+
# 0: At Retransfer Position 1:At Contact IC Encoder 2: At No-Contact IC encoder
|
|
41
|
+
# 3: At MAG encoder Greater than 3: Reserved
|
|
42
|
+
#
|
|
43
|
+
# Byte 1 Bit 0
|
|
44
|
+
# Load Mode: The way to load the card
|
|
45
|
+
# 0: From the card tray
|
|
46
|
+
# 1: From the right side card entrance
|
|
47
|
+
|
|
48
|
+
card_position = { pu: nil, position: nil, load_mode: nil}
|
|
49
|
+
card_position[:pu] = resp.getbyte(0) & 0x4 != 0 ? :no_card_in_printer : :card_in_printer
|
|
50
|
+
|
|
51
|
+
card_position[:position] = case resp.getbyte(7)
|
|
52
|
+
when 0 then :retransfer
|
|
53
|
+
when 1 then :contact
|
|
54
|
+
when 2 then :contactless
|
|
55
|
+
when 3 then :magnetstripe
|
|
56
|
+
else raise "Invalid card_position: #{resp.getbyte(7).inspect}!"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
card_position[:load_mode] = resp.getbyte(0) & 0x1 != 0 ? :right_side : :card_tray
|
|
60
|
+
|
|
61
|
+
card_position
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
ImageLayer2Code = {
|
|
65
|
+
K: 0,
|
|
66
|
+
C: 1,
|
|
67
|
+
M: 2,
|
|
68
|
+
Y: 3,
|
|
69
|
+
UV: 4,
|
|
70
|
+
PeelOff: 5
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
def image_out(layer, data, buffer=0)
|
|
74
|
+
buffer = Buffer2Code[buffer] || buffer
|
|
75
|
+
layer = ImageLayer2Code[layer] || layer
|
|
76
|
+
|
|
77
|
+
@dev.image_out(layer, data, buffer)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Notice: As K LUT is used internally, K must not be specified.
|
|
81
|
+
LutLayer2Code = {
|
|
82
|
+
K: 0,
|
|
83
|
+
C: 2,
|
|
84
|
+
M: 4,
|
|
85
|
+
Y: 6
|
|
86
|
+
}
|
|
87
|
+
def lut=(layer, lut)
|
|
88
|
+
layer = LutLayer2Code[layer] ? LutLayer2Code[layer] : layer
|
|
89
|
+
|
|
90
|
+
data = FFI::MemoryPointer.new :char, 256
|
|
91
|
+
data.write_bytes lut
|
|
92
|
+
|
|
93
|
+
check_returncode C.CXCMD_DefineLUT(@slot, @id, data.size, data)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
Buffer2Code = {
|
|
97
|
+
frontside: 0,
|
|
98
|
+
backside: 1,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
PrintColor2Code = {
|
|
102
|
+
YMC: 0b1,
|
|
103
|
+
K: 0b10,
|
|
104
|
+
UV: 0b100,
|
|
105
|
+
PeelOff: 0b1000
|
|
106
|
+
}
|
|
107
|
+
def print(color=[:YMC, :K], buffer=0, async=false)
|
|
108
|
+
buffer = Buffer2Code[buffer] || buffer
|
|
109
|
+
color = color.map{|c| PrintColor2Code[c] }.inject(0, &:|) if color.kind_of?(Array)
|
|
110
|
+
async = async ? 1 : 0
|
|
111
|
+
|
|
112
|
+
@dev.print(color, buffer, async)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
Position2Code = {
|
|
116
|
+
retransfer: 0,
|
|
117
|
+
contact: 1,
|
|
118
|
+
contactless: 2,
|
|
119
|
+
magnetstripe: 3,
|
|
120
|
+
eject: 4
|
|
121
|
+
}
|
|
122
|
+
def load_card(pos=:retransfer, flip=false, adjusted=false, async=false)
|
|
123
|
+
pos = Position2Code[pos] ? Position2Code[pos] : pos
|
|
124
|
+
flip = flip ? 1 : 0
|
|
125
|
+
adjusted = adjusted ? 1 : 0 # This setting is effective only when Destination is NG Card outlet
|
|
126
|
+
async = async ? 1 : 0
|
|
127
|
+
|
|
128
|
+
@dev.load_card(pos, flip, adjusted, async)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def move_card(pos=:retransfer, flip=false, adjusted=false, async=false)
|
|
132
|
+
pos = Position2Code[pos] ? Position2Code[pos] : pos
|
|
133
|
+
flip = flip ? 1 : 0
|
|
134
|
+
adjusted = adjusted ? 1 : 0 # This setting is effective only when Destination is NG Card outlet
|
|
135
|
+
async = async ? 1 : 0
|
|
136
|
+
|
|
137
|
+
@dev.move_card(pos, flip, adjusted, async)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def retransfer_and_eject(async=false)
|
|
141
|
+
async = async ? 1 : 0
|
|
142
|
+
@dev.retransfer_and_eject(async)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def retransfer_and_turn(async=false)
|
|
146
|
+
async = async ? 1 : 0
|
|
147
|
+
@dev.retransfer_and_turn(async)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
MagFormat = {
|
|
151
|
+
jis2_7bit: [0x07, 69], # 69 charcters at most
|
|
152
|
+
iso1_6bit: [0x16, 76], # 76 charcters at most
|
|
153
|
+
iso1_7bit: [0x17, 69], # 69 charcters at most
|
|
154
|
+
iso2_4bit: [0x24, 37], # 37 charcters at most
|
|
155
|
+
iso3_4bit: [0x34, 104], # 104 charcters at most
|
|
156
|
+
iso3_7bit: [0x37, 69], # 69 charcters at most
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
def write_mag(format, data)
|
|
160
|
+
format, len = MagFormat[format] || format
|
|
161
|
+
@dev.write_mag(format, len, data)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def read_mag(format)
|
|
165
|
+
format, len = MagFormat[format] || format
|
|
166
|
+
@dev.read_mag(format, len)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
IC_Types = {
|
|
170
|
+
contact: 0,
|
|
171
|
+
contactless: 1,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
IC_Actions = {
|
|
175
|
+
contact: 0,
|
|
176
|
+
release: 1,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
def ic_control(type, action)
|
|
180
|
+
type = IC_Types[type] || type
|
|
181
|
+
action = IC_Actions[action] || action
|
|
182
|
+
@dev.ic_control(type, action)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
class AttrDescription < Struct.new(:name, :offs_read, :offs_write, :default, :typ, :params)
|
|
186
|
+
def to_attribute
|
|
187
|
+
ext_type, ext_params = case typ
|
|
188
|
+
when :byte
|
|
189
|
+
[ :int, params || (0..0xff) ]
|
|
190
|
+
when :word
|
|
191
|
+
[ :int, params || (0..0xffff) ]
|
|
192
|
+
when :dword
|
|
193
|
+
[ :int, params || (0..0xffffffff) ]
|
|
194
|
+
when :set, :ascii
|
|
195
|
+
[ typ, params ]
|
|
196
|
+
else
|
|
197
|
+
raise "invalid attr type #{typ}"
|
|
198
|
+
end
|
|
199
|
+
Attribute.new(name, !!offs_write, default, ext_type, ext_params)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
Attribute = Struct.new(:name, :writeable, :default, :typ, :params, :value)
|
|
204
|
+
|
|
205
|
+
def self.to_attr_desc(hash)
|
|
206
|
+
hash.map do |key, args|
|
|
207
|
+
AttrDescription.new(key, *args).freeze
|
|
208
|
+
end.freeze
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def self.make_range(hash)
|
|
212
|
+
byte_min = hash.inject(9999999){|m,(k, v)| [m, k].min }
|
|
213
|
+
byte_max = hash.inject(-9999999){|m,(k, v)| [m, k].max }
|
|
214
|
+
reverse = hash[byte_min].to_i > hash[byte_max].to_i
|
|
215
|
+
range = byte_min+1 .. byte_max-1
|
|
216
|
+
rhash = range.to_a.inject({}) do |h,k|
|
|
217
|
+
v = reverse ? byte_min + hash[byte_min].to_i - k : k - byte_min + hash[byte_min].to_i
|
|
218
|
+
h[k] = v.to_s # + " (#{k})"
|
|
219
|
+
h
|
|
220
|
+
end
|
|
221
|
+
rhash.merge(hash).sort_by{|k,v| k }.inject({}){|h,(k,v)| h[k]=v; h }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
ModeSenseInkAttrs = to_attr_desc({
|
|
225
|
+
ink_code: [2, nil, nil, :set, {0x00 => 'YMCK', 0x02 => 'YMCK-PO', 0x03 => 'K', 0x04 => 'YMCKK', 0x05 => 'YMCK-UV'}],
|
|
226
|
+
ink_number_printed: [4, nil, nil, :word],
|
|
227
|
+
ink_lot_number: [8, nil, nil, :ascii, 6],
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
ModeSensePrintAttrs = to_attr_desc({
|
|
231
|
+
print_ink_code: [21, nil, nil, :set, {0 => 'YMCK', 2 => 'YMCK-PO', 3 => 'K', 4 => 'YMCKK', 5 => 'YMCK-UV'}],
|
|
232
|
+
print_resin_black_energy: [41, 13, 3, :set, make_range(0 => "-3 (bright)", 8 => "5 (dark)")],
|
|
233
|
+
print_resin_black_mode: [42, 14, 0, :set, {0 => 'Standard', 1 => 'Fine'}],
|
|
234
|
+
print_a0_energy: [43, 15, 3, :set, make_range(0 => "-3 (bright)", 8 => "5 (dark)")],
|
|
235
|
+
print_a1_energy: [44, 16, 3, :set, make_range(0 => "-3 (bright)", 8 => "5 (dark)")],
|
|
236
|
+
print_film_code: [20, 17, 0, :set, {0 => 'Standard (1000 panels)', 2 => 'Standard (750panels)'}],
|
|
237
|
+
print_roller_temp_retransfer: [33, 4, 4, :set, make_range(0 => "-3 (low)", 5 => "2 (high)")],
|
|
238
|
+
print_velocity_front: [34, 5, 0, :set, make_range(0 => "2 (Fast)", 12 => "-10 (Slow)")],
|
|
239
|
+
print_velocity_back: [35, 6, 0, :set, make_range(0 => "2 (Fast)", 12 => "-10 (Slow)")],
|
|
240
|
+
|
|
241
|
+
print_buzzer_mode: [45, 21, 0, :set, {0 => 'Buzzer is enabled', 1 => 'Buzzer is disabled'}],
|
|
242
|
+
print_power_save_minutes: [46, 22, 8, :set, {0 =>'5', 1 =>'10', 2 =>'15', 3 =>'20', 4 =>'25', 5 =>'30', 6 =>'45', 7 =>'60', 8 =>'Off'}],
|
|
243
|
+
|
|
244
|
+
print_roller_temp_card_fix: [36, 7, 3, :set, make_range(0 => "-5 (low)", 5 => "0 (high)").merge(10 => "Off")],
|
|
245
|
+
print_velocity_card_fix: [37, 8, 4, :set, make_range(0 => "-2 (slow)", 4 => "2 (fast)")],
|
|
246
|
+
print_peel_off_wait_seconds: [39, 10, 0, :byte, 0..15],
|
|
247
|
+
|
|
248
|
+
print_card_code: [22, 19, 0, :set, {0 => 'Standard', 2 => 'Thin card (Card thickness is 0.25mm)'}],
|
|
249
|
+
print_revision_number: [40, nil, nil, :byte],
|
|
250
|
+
print_film_quantity: [47, nil, nil, :byte, 0..10],
|
|
251
|
+
print_ink_quantity: [48, nil, nil, :byte, 0..50],
|
|
252
|
+
print_card_quantity: [49, nil, nil, :set, {0 => 'Greater than 25 cards', 1 => 'From 1 to 24 cards', 2 => 'No cards', 3 => 'Right Side Card loading mode'}],
|
|
253
|
+
print_resolution_x: [4, nil, nil, :word],
|
|
254
|
+
print_resolution_y: [6, nil, nil, :word],
|
|
255
|
+
print_card_size_x: [12, nil, nil, :word],
|
|
256
|
+
print_card_size_y: [14, nil, nil, :word],
|
|
257
|
+
print_mg_mode: [17, nil, nil, :set, {0 => 'None', 1 => 'MAG Encoder', 2 => 'JIS MAG Encoder'}],
|
|
258
|
+
print_ic_mode_contactless: [19, nil, nil, :set, {0 => 'None', 2 => 'External small IC Encoder', 3 => 'External large IC Encoder'}],
|
|
259
|
+
print_ic_mode_contact: [18, nil, nil, :set, {0 => 'None', 1 => 'Embedded IC Encoder', 2 => 'External IC Encoder'}],
|
|
260
|
+
print_position_x: [24, nil, nil, :word],
|
|
261
|
+
print_position_y: [26, nil, nil, :word],
|
|
262
|
+
print_size_x: [28, nil, nil, :word],
|
|
263
|
+
print_size_y: [30, nil, nil, :word],
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
ModeSenseEncodeAttrs = to_attr_desc({
|
|
267
|
+
mag_iso_mode: [2, 2, 0, :set, {0 => 'No ISO MAG encoder', 1 => '300 Oe (Lo-Co)', 2 => '2750 Oe (Hi-Co)'}],
|
|
268
|
+
mag_read_write_retry: [7, 7, 0, :byte, 0..3],
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
ModeSensePages = {
|
|
272
|
+
ink: [0x23, 4+40, [[ModeSenseInkAttrs, 0]]],
|
|
273
|
+
print: [0x28, 4+50, [[ModeSensePrintAttrs, 0]]],
|
|
274
|
+
mag: [0x2a, 4+10, [[ModeSenseEncodeAttrs, 0]]],
|
|
275
|
+
all: [0x3f, 4+100, [[ModeSenseInkAttrs, 0], [ModeSensePrintAttrs, 40], [ModeSenseEncodeAttrs, 40+50]]],
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
LogSenseAttrs = to_attr_desc({
|
|
279
|
+
log_total_count: [8, nil, nil, :dword],
|
|
280
|
+
log_free_count: [16, nil, nil, :dword],
|
|
281
|
+
log_head_count: [24, nil, nil, :dword],
|
|
282
|
+
log_cleaning_count: [32, nil, nil, :dword],
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
LogSensePages = {
|
|
286
|
+
log: [0x38, 36, [[LogSenseAttrs, 0]]],
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
def mode_sense(page_sym)
|
|
290
|
+
page, len, attr_lists = ModeSensePages[page_sym] || raise("invalid page: #{page_sym.inspect} not in #{ModeSensePages.keys.inspect}")
|
|
291
|
+
data = @dev.mode_sense(page, len)[4..-1]
|
|
292
|
+
lists = attr_lists.map do |attr_list, offset|
|
|
293
|
+
data_to_attrs(data[offset..-1], attr_list)
|
|
294
|
+
end
|
|
295
|
+
lists.inject([], &:+)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
ModeSelectPages = {
|
|
299
|
+
print: [0x28, 23, [[ModeSensePrintAttrs, 0]]],
|
|
300
|
+
mag: [0x2a, 10, [[ModeSenseEncodeAttrs, 0]]],
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
def mode_select(page_sym, attrs={})
|
|
304
|
+
page, len, attr_lists = ModeSelectPages[page_sym] || raise("invalid page: #{page_sym.inspect} not in #{ModeSelectPages.keys.inspect}")
|
|
305
|
+
|
|
306
|
+
data = [0].pack("C") * len
|
|
307
|
+
data[0, 2] = [0x28, 0x15].pack("CC") if page == 0x28
|
|
308
|
+
data[0, 2] = [0x2a, 0x08].pack("CC") if page == 0x2a
|
|
309
|
+
lists = attr_lists.map do |attr_list, offset|
|
|
310
|
+
data[offset..-1] = attrs_to_data(attr_list, data[offset..-1], attrs)
|
|
311
|
+
end
|
|
312
|
+
raise "invalid data length #{data.bytesize}" if data.bytesize != len
|
|
313
|
+
@dev.mode_select(page, data)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def log_sense(page_sym)
|
|
317
|
+
page, len, attr_lists = LogSensePages[page_sym] || raise("invalid page: #{page_sym.inspect} not in #{LogSensePages.keys.inspect}")
|
|
318
|
+
data = @dev.log_sense(page, len)
|
|
319
|
+
lists = attr_lists.map do |attr_list, offset|
|
|
320
|
+
data_to_attrs(data[offset..-1], attr_list)
|
|
321
|
+
end
|
|
322
|
+
lists.inject([], &:+)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def log_select
|
|
326
|
+
@dev.log_select
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def self.mode_sense_attrs(page_sym)
|
|
330
|
+
_page, _len, attr_lists = ModeSensePages[page_sym] || raise("invalid page: #{page_sym.inspect} not in #{ModeSensePages.keys.inspect}")
|
|
331
|
+
attr_lists.map(&:first).inject([], &:+).map{|a| a.to_attribute }
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def self.log_sense_attrs(page_sym)
|
|
335
|
+
_page, _len, attr_lists = LogSensePages[page_sym] || raise("invalid page: #{page_sym.inspect} not in #{LogSensePages.keys.inspect}")
|
|
336
|
+
attr_lists.map(&:first).inject([], &:+).map{|a| a.to_attribute }
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
private
|
|
340
|
+
|
|
341
|
+
def data_to_attrs(data, attr_list)
|
|
342
|
+
attr_list.map do |attr|
|
|
343
|
+
val = case attr.typ
|
|
344
|
+
when :byte
|
|
345
|
+
data[attr.offs_read, 1].getbyte(0)
|
|
346
|
+
when :word
|
|
347
|
+
data[attr.offs_read, 2].unpack("n")[0]
|
|
348
|
+
when :dword
|
|
349
|
+
data[attr.offs_read, 4].unpack("N")[0]
|
|
350
|
+
when :set
|
|
351
|
+
data[attr.offs_read, 1].getbyte(0)
|
|
352
|
+
when :ascii
|
|
353
|
+
data[attr.offs_read, attr.params]
|
|
354
|
+
else
|
|
355
|
+
raise "invalid attr type #{attr.typ}"
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
nattr = attr.to_attribute
|
|
359
|
+
nattr.value = val
|
|
360
|
+
nattr
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def attrs_to_data(attr_list, data, attrs)
|
|
365
|
+
data = data.dup
|
|
366
|
+
attrs.each do |name, value|
|
|
367
|
+
attr = attr_list.find{|a| a.name.to_s == name.to_s }
|
|
368
|
+
raise("invalid attr name #{name.inspect}") unless attr
|
|
369
|
+
|
|
370
|
+
case attr.typ
|
|
371
|
+
when :byte
|
|
372
|
+
if attr.params
|
|
373
|
+
raise("value out of range #{attr.params.inspect}: #{value.inspect}") unless attr.params === value
|
|
374
|
+
end
|
|
375
|
+
data[attr.offs_write, 1] = [value].pack("C")
|
|
376
|
+
when :word
|
|
377
|
+
if attr.params
|
|
378
|
+
raise("value out of range #{attr.params.inspect}: #{value.inspect}") unless attr.params === value
|
|
379
|
+
end
|
|
380
|
+
data[attr.offs_write, 2] = [value].pack("n")
|
|
381
|
+
when :dword
|
|
382
|
+
if attr.params
|
|
383
|
+
raise("value out of range #{attr.params.inspect}: #{value.inspect}") unless attr.params === value
|
|
384
|
+
end
|
|
385
|
+
data[attr.offs_write, 4] = [value].pack("N")
|
|
386
|
+
when :set
|
|
387
|
+
val = case value
|
|
388
|
+
when Integer then value
|
|
389
|
+
when String
|
|
390
|
+
attr.params[value] || raise("invalid set value #{value.inspect}")
|
|
391
|
+
else
|
|
392
|
+
raise("invalid set value #{value.inspect}")
|
|
393
|
+
end
|
|
394
|
+
data[attr.offs_write, 1] = [value].pack("C")
|
|
395
|
+
when :ascii
|
|
396
|
+
data[attr.offs_write, attr.params] = value
|
|
397
|
+
else
|
|
398
|
+
raise "invalid attr type #{attr.typ}"
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
data
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
class CX320_DLL < CX320
|
|
406
|
+
def self.devices(*args)
|
|
407
|
+
super(DeviceDll, *args)
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
class CX320_USB < CX320
|
|
412
|
+
def self.devices(*args)
|
|
413
|
+
super(DeviceUsb, *args)
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
class CX320_SIMU < CX320
|
|
418
|
+
def self.devices(*args)
|
|
419
|
+
super(DeviceSimu, *args)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'libcx320/c'
|
|
2
|
+
|
|
3
|
+
module LibCX320
|
|
4
|
+
class DeviceDll
|
|
5
|
+
extend ErrorHandling
|
|
6
|
+
include ErrorHandling
|
|
7
|
+
|
|
8
|
+
def self.devices
|
|
9
|
+
slot = FFI::MemoryPointer.new :int
|
|
10
|
+
id = FFI::MemoryPointer.new :int
|
|
11
|
+
|
|
12
|
+
devs = [];
|
|
13
|
+
begin
|
|
14
|
+
check_returncode C.CXCMD_ScanCX320(slot, id)
|
|
15
|
+
rescue NoPrinter, NoMorePrinter
|
|
16
|
+
else
|
|
17
|
+
devs << new(slot.read_int, id.read_int)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
loop do
|
|
21
|
+
slot.write_int slot.read_int
|
|
22
|
+
id.write_int id.read_int
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
check_returncode C.CXCMD_ScanCX320Next(slot, id)
|
|
26
|
+
rescue NoPrinter, NoMorePrinter
|
|
27
|
+
# Suche beim ersten Fehler beenden
|
|
28
|
+
break
|
|
29
|
+
else
|
|
30
|
+
devs << new(slot.read_int, id.read_int)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
devs
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def initialize(slot, id)
|
|
37
|
+
@slot = slot
|
|
38
|
+
@id = id
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def connected?
|
|
42
|
+
slot = FFI::MemoryPointer.new :int
|
|
43
|
+
slot.write_int @slot
|
|
44
|
+
id = FFI::MemoryPointer.new :int
|
|
45
|
+
id.write_int @id
|
|
46
|
+
|
|
47
|
+
C.CXCMD_CheckIfConnected(slot, id)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def close
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def ready?
|
|
54
|
+
check_returncode C.CXCMD_TestUnitReady(@slot, @id)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def rezero_unit
|
|
58
|
+
check_returncode C.CXCMD_RezeroUnit(@slot, @id)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def get_current_card_position
|
|
62
|
+
pos = FFI::MemoryPointer.new :char, 8
|
|
63
|
+
check_returncode C.CXCMD_ReadPosition(@slot, @id, pos)
|
|
64
|
+
pos.read_bytes(8)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def image_out(layer, data, buffer)
|
|
68
|
+
check_returncode C.CXCMD_ImageOut(@slot, @id, data, data.size, layer, buffer)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def print(color, buffer, async)
|
|
72
|
+
check_returncode C.CXCMD_Print(@slot, @id, color, buffer, async)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def load_card(pos, flip, adjusted, async)
|
|
76
|
+
check_returncode C.CXCMD_LoadCard(@slot, @id, pos, flip, adjusted, async)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def move_card(pos, flip, adjusted, async)
|
|
80
|
+
check_returncode C.CXCMD_MoveCard(@slot, @id, pos, flip, adjusted, async)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def retransfer_and_eject(async)
|
|
84
|
+
check_returncode C.CXCMD_RetransferAndEject(@slot, @id, async)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def retransfer_and_turn(async)
|
|
88
|
+
check_returncode C.CXCMD_RetransferAndTurn(@slot, @id, async)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def write_mag(format, _len, data)
|
|
93
|
+
cdata = FFI::MemoryPointer.from_string(data)
|
|
94
|
+
check_returncode C.CXCMD_WriteMagData(@slot, @id, cdata, data.bytesize, format)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def read_mag(format, _len)
|
|
98
|
+
cdata = FFI::MemoryPointer.new(:char, 105)
|
|
99
|
+
clen = FFI::MemoryPointer.new(:int)
|
|
100
|
+
clen.write_int cdata.size
|
|
101
|
+
check_returncode C.CXCMD_ReadMagData(@slot, @id, cdata, clen, format)
|
|
102
|
+
cdata.get_bytes(0, clen.read_int)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def ic_control(type, action)
|
|
106
|
+
check_returncode C.CXCMD_ICControl(@slot, @id, type, action)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def mode_sense(page, len)
|
|
110
|
+
cdata = FFI::MemoryPointer.new(:char, len)
|
|
111
|
+
check_returncode C.CXCMD_ModeSense(@slot, @id, page, cdata)
|
|
112
|
+
cdata.get_bytes(0, cdata.size)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def mode_select(page, data)
|
|
116
|
+
cdata = FFI::MemoryPointer.from_string(data)
|
|
117
|
+
check_returncode C.CXCMD_ModeSelect(@slot, @id, page, cdata)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def log_sense(page, len)
|
|
121
|
+
cdata = FFI::MemoryPointer.new(:char, len)
|
|
122
|
+
check_returncode C.CXCMD_LogSense(@slot, @id, page, cdata)
|
|
123
|
+
cdata.get_bytes(0, cdata.size)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def log_select
|
|
127
|
+
check_returncode C.CXCMD_LogSelect(@slot, @id)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
module LibCX320
|
|
2
|
+
class DeviceSimu
|
|
3
|
+
include ErrorHandling
|
|
4
|
+
|
|
5
|
+
def self.devices
|
|
6
|
+
2.times.map do |idx|
|
|
7
|
+
new(idx)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(devidx)
|
|
12
|
+
@devidx = devidx
|
|
13
|
+
@buffers = [{}, {}]
|
|
14
|
+
@card_pos = nil
|
|
15
|
+
@config = {
|
|
16
|
+
0x23 => ["23:26:00:00:03:e8:00:00:59:48:34:31:34:31:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00".gsub(":","")].pack("H*"),
|
|
17
|
+
0x28 => ["28:30:00:00:01:2c:01:2c:00:00:00:00:03:f5:02:7f:00:00:00:02:00:00:00:00:00:00:00:00:04:0c:02:98:00:04:00:00:03:04:00:00:01:03:00:03:03:00:03:06:22:01".gsub(":","")].pack("H*"),
|
|
18
|
+
0x2a => ["2a:08:00:00:00:00:00:00:00:00".gsub(":","")].pack("H*"),
|
|
19
|
+
0x38 => ["38:00:00:20:00:00:00:04:00:00:00:f5:00:01:00:04:00:00:00:00:00:02:00:04:00:00:04:90:00:03:00:04:00:00:00:f5".gsub(":","")].pack("H*"),
|
|
20
|
+
}
|
|
21
|
+
@config[0x3f] = @config[0x23] + @config[0x28] + @config[0x2a]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def close
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def send_inquiry
|
|
28
|
+
"x" * 60
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def log(text)
|
|
32
|
+
puts text
|
|
33
|
+
end
|
|
34
|
+
private :log
|
|
35
|
+
|
|
36
|
+
def ready?
|
|
37
|
+
log "ready?"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def rezero_unit
|
|
41
|
+
log "rezero_unit"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def get_current_card_position
|
|
45
|
+
[@card_pos ? 0x04 : 0x00, 0, 0, 0, 0, 0, 0, @card_pos].pack("CCCCCCCC")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def image_out(layer, data, buffer)
|
|
49
|
+
@buffers[buffer][layer] = data
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def print(color, buffer, async)
|
|
53
|
+
log "print(#{color}, #{buffer}, #{async})"
|
|
54
|
+
|
|
55
|
+
if @buffers[buffer][1] && @buffers[buffer][2] && @buffers[buffer][3]
|
|
56
|
+
pic = Magick::Image.new(1036, 664)
|
|
57
|
+
pic.import_pixels(0, 0, 1036, 664, "R", @buffers[buffer][1])
|
|
58
|
+
pic.import_pixels(0, 0, 1036, 664, "G", @buffers[buffer][2])
|
|
59
|
+
pic.import_pixels(0, 0, 1036, 664, "B", @buffers[buffer][3])
|
|
60
|
+
begin
|
|
61
|
+
pic.display
|
|
62
|
+
rescue
|
|
63
|
+
pic.write("cx320-cmy.jpeg")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
if @buffers[buffer][0]
|
|
67
|
+
pic = Magick::Image.new(1036, 664)
|
|
68
|
+
%w[R G B].each do |color|
|
|
69
|
+
pic.import_pixels(0, 0, 1036, 664, color, @buffers[buffer][0])
|
|
70
|
+
end
|
|
71
|
+
begin
|
|
72
|
+
pic.display
|
|
73
|
+
rescue
|
|
74
|
+
pic.write("cx320-k.jpeg")
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def load_card(pos, flip, adjusted, async)
|
|
80
|
+
log "load_move_card(#{pos}, #{flip}, #{adjusted}, #{async})"
|
|
81
|
+
raise CommandSequenceError.new("card is already loaded", -0x01052A00) if @card_pos
|
|
82
|
+
@card_pos = pos
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def move_card(pos, flip, adjusted, async)
|
|
86
|
+
log "load_move_card(#{pos}, #{flip}, #{adjusted}, #{async})"
|
|
87
|
+
raise CommandSequenceError.new("no card loaded", -0x01052A00) unless @card_pos
|
|
88
|
+
@card_pos = pos
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def retransfer_and_eject(async)
|
|
92
|
+
log "load_move_card(#{async})"
|
|
93
|
+
raise CommandSequenceError.new("card is not in position retransfer", -0x01052A00) if @card_pos != 0
|
|
94
|
+
@card_pos = nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def retransfer_and_turn(async)
|
|
98
|
+
log "load_move_card(#{async})"
|
|
99
|
+
raise CommandSequenceError.new("card is not in position retransfer", -0x01052A00) if @card_pos != 0
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def write_mag(format, len, data)
|
|
103
|
+
log "write_mag(#{format}, #{len}, #{data.inspect})"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def read_mag(format, len)
|
|
107
|
+
"x" * len
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def ic_control(type, action)
|
|
111
|
+
log "write_mag(#{type}, #{action})"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def mode_sense(page, len)
|
|
115
|
+
log "mode_sense(#{page}, #{len})"
|
|
116
|
+
[len - 1, 0, 0x10, 0].pack("CCCC") + @config[page]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def mode_select(page, data)
|
|
120
|
+
log "mode_select(#{page}, #{data.unpack("H*")[0]})"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def log_sense(page, len)
|
|
124
|
+
log "log_sense(#{page}, #{len})"
|
|
125
|
+
@config[page]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def log_select
|
|
129
|
+
log "log_select()"
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
require 'libusb'
|
|
2
|
+
|
|
3
|
+
module LibCX320
|
|
4
|
+
class DeviceUsb
|
|
5
|
+
include ErrorHandling
|
|
6
|
+
|
|
7
|
+
attr_reader :devh
|
|
8
|
+
|
|
9
|
+
def self.devices
|
|
10
|
+
@@ctx = LIBUSB::Context.new
|
|
11
|
+
|
|
12
|
+
@@ctx.devices(idVendor: 0x04f1, idProduct: [0x4030, 0x4033]).map.with_index do |dev, devidx|
|
|
13
|
+
new(dev, devidx)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def bulk_transfer(**kwargs)
|
|
18
|
+
puts kwargs.inspect[0, 90]
|
|
19
|
+
@devh.bulk_transfer(**kwargs)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def send_command(cdb, data_length, direction=LIBUSB::ENDPOINT_IN)
|
|
23
|
+
ensure_open
|
|
24
|
+
@tag += 1
|
|
25
|
+
expected_tag = @tag
|
|
26
|
+
lun = 0
|
|
27
|
+
len = direction==LIBUSB::ENDPOINT_IN ? data_length : data_length.bytesize
|
|
28
|
+
|
|
29
|
+
cbw = ['USBC', expected_tag, len || 0, direction, lun, cdb.length, cdb].pack('a*VVCCCa*')
|
|
30
|
+
cbw = cbw.ljust(31, "\0")
|
|
31
|
+
|
|
32
|
+
bulk_transfer(endpoint: 0x02, dataOut: cbw)
|
|
33
|
+
|
|
34
|
+
if data_length && direction==LIBUSB::ENDPOINT_IN
|
|
35
|
+
recv = bulk_transfer(endpoint: 0x81, dataIn: data_length)
|
|
36
|
+
if recv[0,4] == "USBC".freeze
|
|
37
|
+
return check_status_urb(recv, expected_tag)
|
|
38
|
+
end
|
|
39
|
+
elsif data_length
|
|
40
|
+
recv_len = 0
|
|
41
|
+
while data_length && !data_length.empty?
|
|
42
|
+
begin
|
|
43
|
+
edata = data_length.slice!(0...0x10000)
|
|
44
|
+
recv_len += bulk_transfer(endpoint: 0x02, dataOut: edata)
|
|
45
|
+
rescue LIBUSB::ERROR_PIPE
|
|
46
|
+
@devh.clear_halt(0x02)
|
|
47
|
+
recv = bulk_transfer(endpoint: 0x81, dataIn: 13, timeout: 1)
|
|
48
|
+
return check_status_urb(recv, expected_tag)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
retries = 5
|
|
54
|
+
begin
|
|
55
|
+
buffer = bulk_transfer(endpoint: 0x81, dataIn: 13, timeout: 999999999)
|
|
56
|
+
check_status_urb(buffer, expected_tag)
|
|
57
|
+
rescue LIBUSB::ERROR_PIPE, UnexpectedPacket
|
|
58
|
+
if (retries-=1)>=0
|
|
59
|
+
@devh.clear_halt(0x81)
|
|
60
|
+
retry
|
|
61
|
+
end
|
|
62
|
+
raise
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
return recv
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def check_status_urb(buffer, expected_tag)
|
|
69
|
+
dCSWSignature, dCSWTag, dCSWDataResidue, bCSWStatus = buffer.unpack('a4VVC')
|
|
70
|
+
|
|
71
|
+
raise UnexpectedPacket, "Unexpected USB packet received" if expected_tag != dCSWTag
|
|
72
|
+
if bCSWStatus != 0
|
|
73
|
+
check_returncode(request_sense_error)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def initialize(dev, devidx)
|
|
78
|
+
@dev = dev
|
|
79
|
+
@devidx = devidx
|
|
80
|
+
@tag = 0
|
|
81
|
+
@devh = nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def ensure_open
|
|
85
|
+
return @devh if @devh
|
|
86
|
+
@devh = @dev.open
|
|
87
|
+
@devh.claim_interface(0)
|
|
88
|
+
|
|
89
|
+
# loop do
|
|
90
|
+
# begin
|
|
91
|
+
# bulk_transfer(endpoint: 0x02, dataOut: "USBC\x01\x00\x00\x00`\x00\x00\x00\x80\x00\x06\x12\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
|
92
|
+
# p ["clear"]
|
|
93
|
+
# bulk_transfer(endpoint: 0x81, dataIn: 1300, timeout: 100)
|
|
94
|
+
# rescue LIBUSB::ERROR_TIMEOUT
|
|
95
|
+
# break
|
|
96
|
+
# end
|
|
97
|
+
# end
|
|
98
|
+
|
|
99
|
+
send_inquiry
|
|
100
|
+
|
|
101
|
+
@devh
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def close
|
|
105
|
+
if @devh
|
|
106
|
+
@devh.release_interface(0)
|
|
107
|
+
@devh.close
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def send_inquiry
|
|
112
|
+
expected_length = 0x60 # INQUIRY_LENGTH
|
|
113
|
+
cdb = [ 0x12, 0, 0, # Inquiry
|
|
114
|
+
expected_length, 0,
|
|
115
|
+
].pack('CCCnC')
|
|
116
|
+
|
|
117
|
+
send_command( cdb, expected_length )
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def request_sense_error
|
|
121
|
+
expected_length = 0x14
|
|
122
|
+
cdb = [ 0x03, 0, 0, expected_length, 0].pack('CCCnC')
|
|
123
|
+
res = send_command( cdb, expected_length )
|
|
124
|
+
|
|
125
|
+
-( 0x01 << 24 | res.getbyte(0x02) << 16 | res.getbyte(0x0c) << 8 | 0 )
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def ready?
|
|
129
|
+
cdb = [ 0, 0].pack('Nn')
|
|
130
|
+
send_command( cdb, nil)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def rezero_unit
|
|
134
|
+
cdb = [ 1, 0, 0].pack('CCN')
|
|
135
|
+
send_command( cdb, nil)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def get_current_card_position
|
|
139
|
+
start = 0
|
|
140
|
+
cdb = [ 0x34, 0, # Pre-Fetch(10)
|
|
141
|
+
start, 0,
|
|
142
|
+
0, 0,
|
|
143
|
+
].pack('CCNCnC')
|
|
144
|
+
expected_length = 0x08
|
|
145
|
+
|
|
146
|
+
send_command(cdb, expected_length)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def image_out(layer, data, buffer)
|
|
150
|
+
cdb = [ 0x2a, 0, layer + buffer*8, 0, 0, data.bytesize, 0].pack('CCCCCNC')
|
|
151
|
+
send_command( cdb, data, LIBUSB::ENDPOINT_OUT )
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def load_move_card(scode, p1, p2, pos)
|
|
155
|
+
cdb = [ 0x31, scode, # load card
|
|
156
|
+
p1, 0,
|
|
157
|
+
p2, 0, pos, 0,
|
|
158
|
+
].pack('CCCCCnCn')
|
|
159
|
+
send_command(cdb, nil)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def print(color, buffer, async)
|
|
163
|
+
load_move_card(0x08, async + color*2, buffer, 0)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def load_card(pos, flip, adjusted, async)
|
|
167
|
+
load_move_card(0x01, async, flip*2 + adjusted*4, pos)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def move_card(pos, flip, adjusted, async)
|
|
171
|
+
load_move_card(0x0b, async, flip*2 + adjusted*4, pos)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def retransfer_and_eject(async)
|
|
175
|
+
load_move_card(0x09, async, 0, 0)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def retransfer_and_turn(async)
|
|
179
|
+
load_move_card(0x0a, async, 0, 0)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def write_mag(format, len, data)
|
|
184
|
+
cdb = [ 0x2f, 0, format, 0, data.bytesize, 0].pack('CNCCnC')
|
|
185
|
+
send_command( cdb, data, LIBUSB::ENDPOINT_OUT )
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def read_mag(format, len)
|
|
189
|
+
cdb = [ 0x2e, 0, format, 0, len, 0].pack('CNCCnC')
|
|
190
|
+
send_command( cdb, len )
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def ic_control(type, action)
|
|
194
|
+
cdb = [ 0x32, type*4 + action, 0, 0].pack('CCNN')
|
|
195
|
+
send_command( cdb, nil )
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def mode_sense(page, len)
|
|
199
|
+
expected_length = len
|
|
200
|
+
cdb = [ 0x1a, 0, page, 0, expected_length, 0].pack('CCCCCC')
|
|
201
|
+
send_command( cdb, expected_length )
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def mode_select(page, data)
|
|
205
|
+
cdb = [ 0x15, 0x10, page, 0, data.bytesize, 0].pack('CCCCCC')
|
|
206
|
+
send_command( cdb, data, LIBUSB::ENDPOINT_OUT )
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def log_sense(page, len)
|
|
210
|
+
expected_length = len
|
|
211
|
+
cdb = [ 0x4d, 0, 0x40 | page, 0, 0, expected_length, 0].pack('CCCnnnC')
|
|
212
|
+
send_command( cdb, expected_length )
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def log_select
|
|
216
|
+
cdb = [ 0x4c, 0x03, 0xc0, 0x00, 0].pack('CCCCN')
|
|
217
|
+
send_command( cdb, nil )
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module LibCX320
|
|
2
|
+
module ErrorHandling
|
|
3
|
+
class Error < RuntimeError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class UnexpectedPacket < Error
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class PrinterError < Error
|
|
10
|
+
attr_reader :code
|
|
11
|
+
def initialize(text, code)
|
|
12
|
+
super(text)
|
|
13
|
+
@code = code
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class UnknownPrinterError < PrinterError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class BusyError < PrinterError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
ErrorById = {
|
|
24
|
+
0x0102D000 => ["No card", "There is no card, or the hopper tray is not closed."],
|
|
25
|
+
0x0102D100 => ["Door Open", "Printer door is opened."],
|
|
26
|
+
0x0102D300 => ["Busy of Transporting", "Busy because of transporting card or retransferring. Note: This error is not returnd from functions. Control Function returns positive value as BUSY."],
|
|
27
|
+
0x0102D400 => ["Busy of Printing", "Busy because of printing. Note: This error is not returnd from functions. Control Function returns positive value as BUSY."],
|
|
28
|
+
0x0102D500 => ["Busy of Transporting and Printing", "Busy because of both “Busy of Transporting” and “Busy of Transporting and Printing”. Note: This error is not returnd from functions. Control Function returns positive value as BUSY."],
|
|
29
|
+
0x0102D600 => ["No Cassette", "Ink ribbon cassette is not attached, or/and Retransfer film cassette is not attached."],
|
|
30
|
+
0x0102D700 => ["No Cleaning Ro.", "Cleaning roller is not attached."],
|
|
31
|
+
0x0102DA00 => ["Preheating", "Printer is on the way of preheating."],
|
|
32
|
+
0x0102DB00 => ["Initializing", "Printer is on the way of initializing."],
|
|
33
|
+
0x0102DC00 => ["Testing or Cleaning", "Printer is on the way of Off-line Test or cleaning."],
|
|
34
|
+
0x0102DD00 => ["On Setting or Transport Mode", "Printer is in the setting mode or transporting mode."],
|
|
35
|
+
0x0102DE00 => ["Not Ready for Download", "Firmware download cannot be done as printer is not in Download mode."],
|
|
36
|
+
0x0102FD00 => ["Sleeping", "Printer is in the power save mode. Note) To exit this, initializing printer, which is pressing ENTER button after RESET button or sending REZERO command, is required."],
|
|
37
|
+
0x0102FE00 => ["Password Error", "Password certification is not done."],
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
0x01039000 => ["Jam(Hopper)", "The card does not arrive the card supply sensor within a predefined time."],
|
|
41
|
+
0x01039100 => ["Jam(TurnOver)", "The card does not arrive the sensor inside the turnover unit within a predefined time."],
|
|
42
|
+
0x01039200 => ["Jam(MG)", "The card does not arrive at the card edge sensor within a predefined time after leaving turnover unit. Also in case of magnetic encoding, when detection by the start position sensor of the MG unit is not possible."],
|
|
43
|
+
0x01039300 => ["Jam(Transfer)", "The card does not arrive the card outlet sensor within a predefined time after leaving the card edge sensor."],
|
|
44
|
+
0x01039400 => ["Jam(Discharge)", "The card stops at the card outlet sensor."],
|
|
45
|
+
0x01039500 => ["Load Failure", "The card is not loaded within 10 seconds in Right Side Card Loading mode. Note) Load Card command can be accepted even if this error is activated."],
|
|
46
|
+
0x0103A000 => ["Media Broken", "Retransfer film is broken."],
|
|
47
|
+
0x0103A100 => ["Media Search", "Mark on the retransfer film could not be detected."],
|
|
48
|
+
0x0103AD00 => ["MG Write Error", "Writing error to the magnetic stripe happens."],
|
|
49
|
+
0x0103AE00 => ["MG Read Error", "Reading error from the magnetic stripe happens."],
|
|
50
|
+
0x0103B000 => ["Ink Broken", "Ink ribbon is broken."],
|
|
51
|
+
0x0103B100 => ["Ink Search", "Mark on the ink ribbon could not be detected, or TAG on the ink ribbon is invalid."],
|
|
52
|
+
0x0103BB00 => ["EXT. Jam", "Card jam happens in the external IC unit."],
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
0x01044400 => ["Hardware Timeout", "Time out was detected by the printer firmware."],
|
|
56
|
+
0x0104A900 => ["MG Unconnected", "MG unit is not attached correctly."],
|
|
57
|
+
0x0104AB00 => ["MG Mechanical", "Mechanical error happens in the MG unit."],
|
|
58
|
+
0x0104AC00 => ["MG Hardware", "Hardware error happens in the MG unit."],
|
|
59
|
+
0x0104AF00 => ["MG Communicate", "Communication error happens between printer and MG unit."],
|
|
60
|
+
0x0104B900 => ["EXT. Unconnected", "External IC unit is not attached correctly."],
|
|
61
|
+
0x0104BA00 => ["EXT. SW Setting", "Dip switch setting in the external IC unit is not correct."],
|
|
62
|
+
0x0104BE00 => ["EXT. Communicate", "Communication error happens between printer and external IC unit."],
|
|
63
|
+
0x0104BF00 => ["EXT2. Communicate", "Communication error happens between printer and laminator."],
|
|
64
|
+
0x0104C000 => ["Turn Over Unit", "Turnover unit is out of order."],
|
|
65
|
+
0x0104C100 => ["Heater Cam", "Heater Cam is out order."],
|
|
66
|
+
0x0104D800 => ["Hardware", "Circuit trouble was detected at the initialization. Ex. Vth power cannot be put out from the power supply unit."],
|
|
67
|
+
0x0104F000 => ["TR Overheat", "The temperature of retransfer roller is too hot."],
|
|
68
|
+
0x0104F100 => ["TR Broken", "Retransfer roller is out of order."],
|
|
69
|
+
0x0104F200 => ["TR Sensor Broken", "Retransfer roller thermister is out of order."],
|
|
70
|
+
0x0104F300 => ["RR Overheat", "The temperature of bend remdil roller is too hot."],
|
|
71
|
+
0x0104F400 => ["RR Broken", "Bend remdil roller is out of order."],
|
|
72
|
+
0x0104F500 => ["RR Sensor Broken", "Bend remdil roller thermister is out of order."],
|
|
73
|
+
0x0104F600 => ["Overcool", "The temperature in the printer is too cool."],
|
|
74
|
+
0x0104F800 => ["Head Overheat", "The temperature of the thermal head is too hot."],
|
|
75
|
+
0x0104FA00 => ["EEPROM Broken", "EEPROM on the CPU circuit board or the head EEPROM is defective."],
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
0x01051A00 => ["Parameter List Length Error", "The content of command is invalid. Parameter list length value in CDB or Page Data is invalid."],
|
|
79
|
+
0x01052000 => ["Invalid Command Operation Code", "The content of command is invalid. Operation Code in CDB is invalid."],
|
|
80
|
+
0x01052400 => ["Illegal Field in CDB", "The content of command is invalid. The data in CDB is invalid."],
|
|
81
|
+
0x01052500 => ["Invalid LUN", "The content of command is invalid. LUN value in CDB is invalid."],
|
|
82
|
+
0x01052600 => ["Invalid Field in Parameter List", "The content of command is invalid. The data in Page Data is invalid."],
|
|
83
|
+
0x01052700 => ["Invalid Color Code in CDB", "Invalid ink is specified.."],
|
|
84
|
+
0x01052A00 => ["Command Sequence Error", "The command is issued in bad order. Ex. Load Card is done when the card is in the printer."],
|
|
85
|
+
0x01052B00 => ["MG Data Error", "MG data from the host computer is invalid."],
|
|
86
|
+
0x01052C00 => ["IC Encoder not installed", "There is no specified IC Encoder."],
|
|
87
|
+
0x01052D00 => ["MG Encoder not installed", "There is no specified MG Encoder."],
|
|
88
|
+
0x0105FB00 => ["Invalid Download Data", "Download data from the host computer is invalid."],
|
|
89
|
+
0x01062800 => ["Medium Changed", "Printer was initialized by pressing RESET button."],
|
|
90
|
+
0x01062900 => ["Power On or Bus Device Reset Occurred", "Printer was initialized by turning on the printer power."],
|
|
91
|
+
0x0142A200 => ["Media Run Out", "End of retransfer film is detected."],
|
|
92
|
+
0x0142B200 => ["Ink Run Out", "End of ink ribbon is detected."],
|
|
93
|
+
|
|
94
|
+
0x02000006 => ["No Printer", "No printer found."],
|
|
95
|
+
0x09000002 => ["No More Printer", "No further printer found."],
|
|
96
|
+
|
|
97
|
+
-1 => ["Busy Port Manager", "CX Port Manager did not send command to the printer because of Printer’s condition. This error never happens."],
|
|
98
|
+
-2 => ["Busy Target", "Card Printer rejected the command because it is on the way of moving the card."],
|
|
99
|
+
-3 => ["Busy Busy", "CX-320 Control DLL rejected the command because the command issued by other process is on the way of processing."],
|
|
100
|
+
-4 => ["Busy Target2", "Card Printer rejected the command because it is on the way of printing on the retransfer film."],
|
|
101
|
+
-5 => ["Busy Target3", "Card Printer rejected the command because of both _TARGET_BUSY1 and _TARGET_BUSY2."],
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
ErrorById.each do |id, tt|
|
|
105
|
+
name, text = tt
|
|
106
|
+
klname = name.gsub(/[^a-z0-9]/i, " ").gsub(/ +([a-z])/i){ $1.upcase }.strip
|
|
107
|
+
base_klass = case klname
|
|
108
|
+
when /^Busy/ then BusyError
|
|
109
|
+
else PrinterError
|
|
110
|
+
end
|
|
111
|
+
klass = Class.new(base_klass)
|
|
112
|
+
const_set(klname, klass)
|
|
113
|
+
tt << klass
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def check_returncode(code)
|
|
117
|
+
return code if code==0
|
|
118
|
+
mc = -code
|
|
119
|
+
codes = [mc >> 24 & 0xff, mc >> 16 & 0xff, mc >> 8 & 0xff, mc & 0xff]
|
|
120
|
+
klname, text, klass = ErrorById[mc]
|
|
121
|
+
|
|
122
|
+
if klname
|
|
123
|
+
raise klass.new("CX320: %s (code %02x %02x %02x %02x)" % [text, *codes], code)
|
|
124
|
+
else
|
|
125
|
+
raise UnknownPrinterError.new("CX320: error %02x %02x %02x %02x" % codes, code)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
data/lib/libcx320.rb
ADDED
data/libcx320.gemspec
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'libcx320/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "libcx320"
|
|
8
|
+
spec.version = LibCX320::VERSION
|
|
9
|
+
spec.authors = ["Lars Kanis"]
|
|
10
|
+
spec.email = ["lars@greiz-reinsdorf.de"]
|
|
11
|
+
spec.summary = %q{Driver for Retransfer Printer CX-320}
|
|
12
|
+
spec.description = %q{Driver for Retransfer Printer CX-320. Usable per PCP05CT.DLL or LIBUSB.}
|
|
13
|
+
spec.homepage = "https://github.com/larskanis/libcx320"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
23
|
+
end
|
data.tar.gz.sig
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
v��nqI�x}b����m�+P�sI�4܈i�e��A�W�N�U�����Y�+{?.�2=����[Z9���n���Q�D���k�3�\��d�V��|����N(G��U�D��j�4}ڀ��a"�Ct�@I�>s�
|
|
2
|
+
��fQdg�3��N���Er���짰�Ɔ����ƍz����*��Q"��c��h���f��U;�5����n�?~f��� �1�������c�:�������[`ucz5=�`p�UN��сV7dLKoPF�ɫC�� ��rٙq^i�EL����C������RD�U$�G�[���IĽ������p�pl|�|�0}T���=%M��jYn�Vm��פ���Q@%b�C�h���D�mr��GD���Y
|
metadata
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: libcx320
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.5
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Lars Kanis
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain:
|
|
10
|
+
- |
|
|
11
|
+
-----BEGIN CERTIFICATE-----
|
|
12
|
+
MIIEBDCCAmygAwIBAgIBBDANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1sYXJz
|
|
13
|
+
L0RDPWdyZWl6LXJlaW5zZG9yZi9EQz1kZTAeFw0yNjAxMDUxMTE5MzRaFw0yNzAx
|
|
14
|
+
MDUxMTE5MzRaMCgxJjAkBgNVBAMMHWxhcnMvREM9Z3JlaXotcmVpbnNkb3JmL0RD
|
|
15
|
+
PWRlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwum6Y1KznfpzXOT/
|
|
16
|
+
mZgJTBbxZuuZF49Fq3K0WA67YBzNlDv95qzSp7V/7Ek3NCcnT7G+2kSuhNo1FhdN
|
|
17
|
+
eSDO/moYebZNAcu3iqLsuzuULXPLuoU0GsMnVMqV9DZPh7cQHE5EBZ7hlzDBK7k/
|
|
18
|
+
8nBMvR0mHo77kIkapHc26UzVq/G0nKLfDsIHXVylto3PjzOumjG6GhmFN4r3cP6e
|
|
19
|
+
SDfl1FSeRYVpt4kmQULz/zdSaOH3AjAq7PM2Z91iGwQvoUXMANH2v89OWjQO/NHe
|
|
20
|
+
JMNDFsmHK/6Ji4Kk48Z3TyscHQnipAID5GhS1oD21/WePdj7GhmbF5gBzkV5uepd
|
|
21
|
+
eJQPgWGwrQW/Z2oPjRuJrRofzWfrMWqbOahj9uth6WSxhNexUtbjk6P8emmXOJi5
|
|
22
|
+
chQPnWX+N3Gj+jjYxqTFdwT7Mj3pv1VHa+aNUbqSPpvJeDyxRIuo9hvzDaBHb/Cg
|
|
23
|
+
9qRVcm8a96n4t7y2lrX1oookY6bkBaxWOMtWlqIprq8JZXM9AgMBAAGjOTA3MAkG
|
|
24
|
+
A1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQ4h1tIyvdUWtMI739xMzTR
|
|
25
|
+
7EfMFzANBgkqhkiG9w0BAQsFAAOCAYEAg/1LuXN3X8xwHVnhRvmBCZYkNErko40y
|
|
26
|
+
juq/qPF9vkPGxLEGaeZF1rv/obTs5SgIGEUkWdRsOl3F6bQN4MYUFlN/n6rPx19g
|
|
27
|
+
CqUMkmRtuFD+9EFBI4twoF2IJS0pYr9tkjUq8mb0VXblvfbEEUf460BJmuBXZTc6
|
|
28
|
+
OoLQHxjhhqhKBoP4lHXg/OMK9dnGn8+5DoKcsyWQvqq/GdK8pi4E47M/egzw54Go
|
|
29
|
+
g+oeyGDsNKOQlnIA9gbyPpExD1+akJ4v88T8jOUnsOkhBBUkpSktC2QmEYIU5e9j
|
|
30
|
+
N7muw6O5Bz3CQuSWIEjj9mMUS2fEEfq2km6zO5vs5eD6TdFnt8AC/HlOrPaxGcUX
|
|
31
|
+
Hjw/K7ZTvZLEb4awRijdy4wx3OlL9FAyZPjYOh8TdJrLl076c7GyimAkgnc8BrL5
|
|
32
|
+
g1vGc759o2t3KNnlUg8VwqkhFJp4gCko1QO/8Io5hPQZOvJw8dmqNiiiHqaDupfl
|
|
33
|
+
CI4mk2K8yQa8xtQ/RmFZxYS5XbHhDJCw
|
|
34
|
+
-----END CERTIFICATE-----
|
|
35
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
36
|
+
dependencies:
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
38
|
+
name: bundler
|
|
39
|
+
requirement: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - "~>"
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '1.7'
|
|
44
|
+
type: :development
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - "~>"
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '1.7'
|
|
51
|
+
- !ruby/object:Gem::Dependency
|
|
52
|
+
name: rake
|
|
53
|
+
requirement: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - "~>"
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: '10.0'
|
|
58
|
+
type: :development
|
|
59
|
+
prerelease: false
|
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - "~>"
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '10.0'
|
|
65
|
+
description: Driver for Retransfer Printer CX-320. Usable per PCP05CT.DLL or LIBUSB.
|
|
66
|
+
email:
|
|
67
|
+
- lars@greiz-reinsdorf.de
|
|
68
|
+
executables: []
|
|
69
|
+
extensions: []
|
|
70
|
+
extra_rdoc_files: []
|
|
71
|
+
files:
|
|
72
|
+
- ".gitignore"
|
|
73
|
+
- Gemfile
|
|
74
|
+
- LICENSE.txt
|
|
75
|
+
- README.md
|
|
76
|
+
- Rakefile
|
|
77
|
+
- lib/libcx320.rb
|
|
78
|
+
- lib/libcx320/c.rb
|
|
79
|
+
- lib/libcx320/cx320.rb
|
|
80
|
+
- lib/libcx320/device_dll.rb
|
|
81
|
+
- lib/libcx320/device_simu.rb
|
|
82
|
+
- lib/libcx320/device_usb.rb
|
|
83
|
+
- lib/libcx320/error_handling.rb
|
|
84
|
+
- lib/libcx320/version.rb
|
|
85
|
+
- libcx320.gemspec
|
|
86
|
+
homepage: https://github.com/larskanis/libcx320
|
|
87
|
+
licenses:
|
|
88
|
+
- MIT
|
|
89
|
+
metadata: {}
|
|
90
|
+
rdoc_options: []
|
|
91
|
+
require_paths:
|
|
92
|
+
- lib
|
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
requirements: []
|
|
104
|
+
rubygems_version: 4.0.16
|
|
105
|
+
specification_version: 4
|
|
106
|
+
summary: Driver for Retransfer Printer CX-320
|
|
107
|
+
test_files: []
|
metadata.gz.sig
ADDED
|
Binary file
|