Firmware of Silead Touchscreen Controller for Jumper EZpad 6 Pro.
Revision | fdc895d636cc81641342c8bbe5e117b75edd3021 (tree) |
---|---|
Zeit | 2017-04-19 15:31:44 |
Autor | Gregor Riepl <onitake@gmai...> |
Commiter | Gregor Riepl |
WIP rewrite of fwtool and the Perl lib
@@ -2,11 +2,58 @@ package Firmware::Silead; | ||
2 | 2 | |
3 | 3 | use strict; |
4 | 4 | use IO::File; |
5 | +use IO::Scalar; | |
5 | 6 | |
6 | 7 | our $MAGIC = 'GSLX'; |
7 | 8 | our $FORMAT = 1; |
8 | 9 | our $HEADER_SIZE = 24; |
9 | 10 | our $PAGE_SIZE = 132; |
11 | +our %formats = ( | |
12 | + 'new' => { | |
13 | + 'load' => sub { | |
14 | + $_[0]->load_new($_[1]) | |
15 | + }, | |
16 | + 'save' => sub { | |
17 | + $_[0]->save_new($_[1]); | |
18 | + }, | |
19 | + 'test' => sub { | |
20 | + return defined Firmware::Silead->load_new($_[0]); | |
21 | + }, | |
22 | + }, | |
23 | + 'header' => { | |
24 | + 'load' => sub { | |
25 | + $_[0]->load_header($_[1]) | |
26 | + }, | |
27 | + 'save' => sub { | |
28 | + $_[0]->save_header($_[1]); | |
29 | + }, | |
30 | + 'test' => sub { | |
31 | + return defined Firmware::Silead->load_header($_[0]); | |
32 | + }, | |
33 | + }, | |
34 | + 'win' => { | |
35 | + 'load' => sub { | |
36 | + $_[0]->load_win($_[1]) | |
37 | + }, | |
38 | + 'save' => sub { | |
39 | + $_[0]->save_win($_[1]); | |
40 | + }, | |
41 | + 'test' => sub { | |
42 | + return defined Firmware::Silead->load_win($_[0]); | |
43 | + }, | |
44 | + }, | |
45 | + 'old' => { | |
46 | + 'load' => sub { | |
47 | + $_[0]->load_old($_[1]) | |
48 | + }, | |
49 | + 'save' => sub { | |
50 | + $_[0]->save_old($_[1]); | |
51 | + }, | |
52 | + 'test' => sub { | |
53 | + return defined Firmware::Silead->load_old($_[0]); | |
54 | + }, | |
55 | + }, | |
56 | +}; | |
10 | 57 | |
11 | 58 | sub _unpack_header { |
12 | 59 | my ($header) = @_; |
@@ -40,18 +87,50 @@ sub new { | ||
40 | 87 | xmirrored => 0, |
41 | 88 | ymirrored => 0, |
42 | 89 | tracking => 0, |
43 | - }, ref $class ? ref $class : $class; | |
90 | + format => undef, | |
91 | + config => [ (0) x 512 ], | |
92 | + }, ref $class || $class; | |
44 | 93 | } |
45 | 94 | |
46 | 95 | sub load { |
47 | - my ($class, $handle) = @_; | |
96 | + my ($class, $handle, $type) = @_; | |
48 | 97 | if (!ref $handle) { |
49 | 98 | $handle = IO::File->new($handle, 'r'); |
50 | 99 | } |
51 | 100 | if (!defined $handle) { |
52 | - $@ = "Invalid file handle"; | |
101 | + $@ = "File name or handle required"; | |
102 | + return undef; | |
103 | + } | |
104 | + if (!defined $type or $type eq 'auto') { | |
105 | + my $here = $handle->tell(); | |
106 | + for my $format (keys(%formats)) { | |
107 | + if (!$handle->seek($here, 0)) { | |
108 | + $@ = "A seekable file handle is required for format autodetection"; | |
109 | + return undef; | |
110 | + } | |
111 | + my $self = $class->new(); | |
112 | + if ($formats{$format}->load($self, $handle)) { | |
113 | + return $self; | |
114 | + } | |
115 | + } | |
116 | + $@ = "Format autodetection failed"; | |
117 | + return undef; | |
118 | + } else { | |
119 | + if (!defined $formats{$type}) { | |
120 | + $@ = "Invalid type"; | |
121 | + return undef; | |
122 | + } | |
123 | + my $self = $class->new(); | |
124 | + if ($formats{$type}->load($self, $handle)) { | |
125 | + return $self; | |
126 | + } | |
127 | + $@ = "Invalid data for format"; | |
53 | 128 | return undef; |
54 | 129 | } |
130 | +} | |
131 | + | |
132 | +sub load_new { | |
133 | + my ($self, $handle) = @_; | |
55 | 134 | binmode $handle; |
56 | 135 | read $handle, my $header, $HEADER_SIZE; |
57 | 136 | my ($magic, $model, $format, $touches, $width, $height, $swapped, $xmirrored, $ymirrored, $tracking, $pages) = _unpack_header $header; |
@@ -63,17 +142,16 @@ sub load { | ||
63 | 142 | $@ = "Invalid file format $format"; |
64 | 143 | return undef; |
65 | 144 | } |
66 | - my $self = bless { | |
67 | - pages => { }, | |
68 | - model => $model, | |
69 | - touches => $touches, | |
70 | - width => $width, | |
71 | - height => $height, | |
72 | - swapped => $swapped, | |
73 | - xmirrored => $xmirrored, | |
74 | - ymirrored => $ymirrored, | |
75 | - tracking => $tracking, | |
76 | - }, ref $class ? ref $class : $class; | |
145 | + $self->{pages} = { }; | |
146 | + $self->{model} = $model; | |
147 | + $self->{touches} = $touches; | |
148 | + $self->{width} = $width; | |
149 | + $self->{height} = $height; | |
150 | + $self->{swapped} = $swapped; | |
151 | + $self->{xmirrored} = $xmirrored; | |
152 | + $self->{ymirrored} = $ymirrored; | |
153 | + $self->{tracking} = $tracking; | |
154 | + $self->{config} = [ (0) x 512 ]; | |
77 | 155 | for (my $i = 0; $i < $pages; $i++) { |
78 | 156 | read $handle, my $buffer, $PAGE_SIZE; |
79 | 157 | my ($address, $size, $data) = _unpack_page $buffer; |
@@ -81,11 +159,12 @@ sub load { | ||
81 | 159 | return undef; |
82 | 160 | } |
83 | 161 | } |
162 | + $self->{format} = 'new'; | |
84 | 163 | return $self; |
85 | 164 | } |
86 | 165 | |
87 | 166 | sub save { |
88 | - my ($self, $handle) = @_; | |
167 | + my ($self, $handle, $type) = @_; | |
89 | 168 | if (!ref $handle) { |
90 | 169 | $handle = IO::File->new($handle, 'w'); |
91 | 170 | } |
@@ -93,6 +172,22 @@ sub save { | ||
93 | 172 | $@ = "Invalid file handle"; |
94 | 173 | return 0; |
95 | 174 | } |
175 | + if (!defined $type or $type eq 'copy') { | |
176 | + if (!defined $self->{format}) { | |
177 | + $@ = "Source format unknown, can't copy"; | |
178 | + return 0; | |
179 | + } | |
180 | + $type = $self->{format}; | |
181 | + } | |
182 | + if (!defined $formats{$type}) { | |
183 | + $@ = "Invalid format $type"; | |
184 | + return 0; | |
185 | + } | |
186 | + return $formats{$type}->save($self, $handle); | |
187 | +} | |
188 | + | |
189 | +sub save_new { | |
190 | + my ($self, $handle) = @_; | |
96 | 191 | binmode $handle; |
97 | 192 | my @pages = $self->get_pages; |
98 | 193 | my $header = _pack_header $self->model, $self->touches, $self->width, $self->height, $self->swapped, $self->xmirrored, $self->ymirrored, $self->tracking, scalar(@pages); |
@@ -106,7 +201,10 @@ sub save { | ||
106 | 201 | } |
107 | 202 | |
108 | 203 | sub unpack { |
109 | - my ($class, $data) = @_; | |
204 | + my ($self, $data) = @_; | |
205 | + if (!ref $self) { | |
206 | + $self = $self->new(); | |
207 | + } | |
110 | 208 | my $header = substr $data, 0, $HEADER_SIZE; |
111 | 209 | my ($magic, $model, $format, $touches, $width, $height, $swapped, $xmirrored, $ymirrored, $tracking, $pages) = _unpack_header $header; |
112 | 210 | if ($magic ne $MAGIC) { |
@@ -117,17 +215,16 @@ sub unpack { | ||
117 | 215 | $@ = "Invalid file format $format"; |
118 | 216 | return undef; |
119 | 217 | } |
120 | - my $self = bless { | |
121 | - pages => { }, | |
122 | - model => $model, | |
123 | - touches => $touches, | |
124 | - width => $width, | |
125 | - height => $height, | |
126 | - swapped => $swapped, | |
127 | - xmirrored => $xmirrored, | |
128 | - ymirrored => $ymirrored, | |
129 | - tracking => $tracking, | |
130 | - }, ref $class ? ref $class : $class; | |
218 | + $self->{pages} = { }; | |
219 | + $self->{model} = $model; | |
220 | + $self->{touches} = $touches; | |
221 | + $self->{width} = $width; | |
222 | + $self->{height} = $height; | |
223 | + $self->{swapped} = $swapped; | |
224 | + $self->{xmirrored} = $xmirrored; | |
225 | + $self->{ymirrored} = $ymirrored; | |
226 | + $self->{tracking} = $tracking; | |
227 | + $self->{config} = [ (0) x 512 ]; | |
131 | 228 | for (my $i = 0; $i < $pages; $i++) { |
132 | 229 | my $buffer = substr $HEADER_SIZE + $i * $PAGE_SIZE, $PAGE_SIZE; |
133 | 230 | my ($address, $size, $data) = _unpack_page $buffer ; |
@@ -152,37 +249,101 @@ sub pack { | ||
152 | 249 | return $data; |
153 | 250 | } |
154 | 251 | |
155 | -sub import_scrambled { | |
252 | +sub load_win { | |
156 | 253 | my ($self, $input) = @_; |
157 | 254 | my $tscfg = ''; |
158 | 255 | for my $byte (split //, $input) { |
159 | 256 | my $descrambled = chr(ord($byte) ^ 0x88); |
160 | 257 | $tscfg .= $descrambled; |
161 | 258 | } |
162 | - return $self->import_tscfg($tscfg); | |
259 | + my $ret = $self->load_header($tscfg); | |
260 | + $self->{format} = 'win'; | |
261 | + return $ret; | |
262 | +} | |
263 | + | |
264 | +sub save_win { | |
265 | + my ($self) = @_; | |
266 | + my $tscfg = $self->save_header; | |
267 | + my $scrambled = ''; | |
268 | + for my $byte (split //, $tscfg) { | |
269 | + $scrambled .= chr(ord($byte) ^ 0x88); | |
270 | + } | |
271 | + return $scrambled; | |
163 | 272 | } |
164 | 273 | |
165 | -sub import_tscfg { | |
274 | +sub load_header { | |
166 | 275 | my ($self, $input) = @_; |
167 | 276 | my ($cfg, $fw) = (0, ''); |
277 | + my @config; | |
168 | 278 | for my $line (split /\n/, $input) { |
169 | - if ($cfg and $line =~ /};/) { | |
279 | + if ($cfg > 0 and $line =~ /};/) { | |
170 | 280 | $cfg = 0; |
171 | 281 | } |
172 | 282 | if ($line =~ /TS_CFG_DATA|GSLX68X_FW/) { |
173 | 283 | $cfg = 1; |
174 | 284 | } |
175 | - if ($cfg) { | |
285 | + if ($cfg == 0 and $line =~ /gsl_config_data_id/) { | |
286 | + $cfg = 2; | |
287 | + } | |
288 | + if ($cfg == 1) { | |
176 | 289 | $line =~ s/\s//g; |
177 | - $line = lc($line); | |
290 | + $line = lc $line; | |
178 | 291 | if ($line =~ /{0x([0-9a-f]+),0x([0-9a-f]+)},/) { |
179 | - my $address = hex($1); | |
180 | - my $data = hex($2); | |
292 | + my $address = hex $1; | |
293 | + my $data = hex $2; | |
181 | 294 | $fw .= pack '(LL)<', $address, $data; |
182 | 295 | } |
296 | + } elsif ($cfg == 2) { | |
297 | + $line =~ s/\s//g; | |
298 | + $line =~ s#//.*$##; | |
299 | + $line = lc $line; | |
300 | + for my $str (split(',', $line)) { | |
301 | + if ($str =~ /0x([a-f0-9]+)/) { | |
302 | + my $value = unpack 'H*', $1; | |
303 | + push @config, $value; | |
304 | + } elsif ($str =~ /([a-f0-9]+)/) { | |
305 | + my $value = int $1; | |
306 | + push @config, $value; | |
307 | + } | |
308 | + } | |
309 | + } | |
310 | + } | |
311 | + if (@config != 512) { | |
312 | + warn "Ignoring invalid config block"; | |
313 | + } else { | |
314 | + $self->{config} = \@config; | |
315 | + } | |
316 | + my $ret = $self->import_fw($fw); | |
317 | + $self->{format} = 'win'; | |
318 | + return $ret; | |
319 | +} | |
320 | + | |
321 | +sub save_header { | |
322 | + my ($self) = @_; | |
323 | + my $tscfg = ''; | |
324 | + $tscfg .= "\n"; | |
325 | + $tscfg .= "unsigned int gsl_config_data_id[512]=\n"; | |
326 | + $tscfg .= "{\n"; | |
327 | + for (my $offset = 0; $offset < @{$self->{config}}; $offset += 4) { | |
328 | + $tscfg .= sprintf "\t0x%08x,0x%08x,0x%08x,0x%08x,\n", $self->{config}->[$offset..($offset+3)]; | |
329 | + } | |
330 | + $tscfg .= "};\n"; | |
331 | + $tscfg .= "TS_CFG_DATA GSL_TS_CFG[] = {\n"; | |
332 | + $tscfg .= "\n"; | |
333 | + my @pages = $self->get_pages; | |
334 | + for my $page (@pages) { | |
335 | + my $pagedata = $self->get_page($page); | |
336 | + $tscfg .= sprintf "{0x%02x,0x%02x}\n", 0xf0, $page; | |
337 | + my $length = length $pagedata; | |
338 | + for (my $offset = 0; $offset + 3 < $length; $offset += 4) { | |
339 | + my $word = substr $pagedata, $offset, 4; | |
340 | + my $value = unpack '(L)<', $word; | |
341 | + $tscfg .= sprintf "{0x%02x,0x%08x}\n", $offset, $value; | |
183 | 342 | } |
184 | 343 | } |
185 | - return $self->import_fw($fw); | |
344 | + $tscfg .= "\n"; | |
345 | + $tscfg .= "};\n"; | |
346 | + return $tscfg; | |
186 | 347 | } |
187 | 348 | |
188 | 349 | sub import_fw { |
@@ -9,81 +9,62 @@ use lib dirname (__FILE__); | ||
9 | 9 | use Firmware::Silead; |
10 | 10 | |
11 | 11 | sub usage() { |
12 | - print STDERR "Usage: fwtool {-i | -c <original.fw> | -s | -x <legacy.fw>} [ -1 | -2 | -3 ] [-w <width>] [-h <height>] [-t <num_touches>] [-f <flags>] <firmware.fw>\n"; | |
13 | - print STDERR "-i Prints statistics and information about new-style firmware.fw\n"; | |
14 | - print STDERR "-c Converts any older firmware format into new-style firmware.fw\n"; | |
15 | - print STDERR "-s Sets parameters and flags\n"; | |
16 | - print STDERR "-x Exports a firmware into plain format, to use with other Linux/Android drivers\n"; | |
17 | - print STDERR " The source firmware format can be specified with these parameters:\n"; | |
18 | - print STDERR "-1 Plain firmware, as used with the Android driver (default)\n"; | |
19 | - print STDERR "-2 Windows GSL_TS_CFG.h firmware\n"; | |
20 | - print STDERR "-3 Scrambled Windows SileadTouch.fw firmware\n"; | |
21 | - print STDERR " For the -c and -s modes, the following parameters may be set:\n"; | |
22 | - print STDERR "-m Sets the controller model (4-byte ASCII string, ex.: 1680)\n"; | |
23 | - print STDERR "-w Sets the width parameter\n"; | |
24 | - print STDERR "-h Sets the height parameter\n"; | |
25 | - print STDERR "-t Sets the number of supported touch points parameter\n"; | |
26 | - print STDERR "-f Sets flags, separated by commas (optional, supported flags: xflip, yflip, swap, track)\n"; | |
27 | - print STDERR " xflip enables horizontal flipping\n"; | |
28 | - print STDERR " yflip enables vertical flipping\n"; | |
29 | - print STDERR " swap enables axis swapping\n"; | |
30 | - print STDERR " track enables in-driver finger tracking (use for controllers that don't support it)\n"; | |
31 | - print STDERR " Each flag may be prefixed with 'no' to disable it.\n"; | |
12 | + print STDERR "Usage: fwtool [MODE] [INPUT] [MODIFIERS] [OUTPUT]\n"; | |
13 | + print STDERR "[MODE] is one of:\n"; | |
14 | + print STDERR "-r (Read-only mode, default) Prints statistics and/or information about firmware\n"; | |
15 | + print STDERR "-w (Read-write mode) Writes a new firmware image, optionally setting flags\n"; | |
16 | + print STDERR "[INPUT] specifies the input:\n"; | |
17 | + print STDERR "-f [FORMAT] (Optional, default: auto) Sets the input file format\n"; | |
18 | + print STDERR "-i [FILE] Specifies the input firmware file\n"; | |
19 | + print STDERR "[MODIFIERS] can be any number of:\n"; | |
20 | + print STDERR "-s [KEY]=[VALUE] Sets flag KEY to VALUE\n"; | |
21 | + print STDERR "[OUTPUT] specifies the output:\n"; | |
22 | + print STDERR "-g [FORMAT] (Optional, default: copy) Sets the output file format\n"; | |
23 | + print STDERR "-o [FILE] (Optional, input will be overwritten if omitted) Specifies the output firmware file\n"; | |
24 | + print STDERR "[FORMAT] is one of:\n"; | |
25 | + print STDERR "auto (Only valid for input) Auto-detect firmware\n"; | |
26 | + print STDERR "copy (Only valid for output) Use the same format as input\n"; | |
27 | + print STDERR "old Old-style binary firmware, as used by the Android driver\n"; | |
28 | + print STDERR "new New-style binary firmware, as used by gslx680-acpi\n"; | |
29 | + print STDERR "header C header file containing a firmware image and calibration data\n"; | |
30 | + print STDERR "win Scrambled firmware, as used by the Windows driver\n"; | |
31 | + print STDERR "[KEY] can be:\n"; | |
32 | + print STDERR "model A 4-character string describing the controller (ex.: 1680, default= )\n"; | |
33 | + print STDERR "width The width of the touch panel, i.e. x coordinate maximum (0-4095, default=4095)\n"; | |
34 | + print STDERR "height The height of the touch panel, i.e. the y coordinate maximum (0-4095, default=4095)\n"; | |
35 | + print STDERR "points The number of supported touch points (1-10, default=10)\n"; | |
36 | + print STDERR "track Enables in-kernel finger tracking (1=enable, 0=disable, default=enable)\n"; | |
37 | + print STDERR "xflip Enables horizontal flipping (1=enable, 0=disable, default=disable)\n"; | |
38 | + print STDERR "yflip Enables vertical flipping (1=enable, 0=disable, default=disable)\n"; | |
39 | + print STDERR "swap Enables x-y axis swapping (1=enable, 0=disable, default=disable)\n"; | |
32 | 40 | -1; |
33 | 41 | } |
34 | 42 | |
35 | -my ($mode, $format, $tscfg, $model, $width, $height, $touches, $flags, $plain) = ('info', 'plain'); | |
43 | +my ($readwrite, $iformat, $ifile, $oformat, $ofile) = (0, 'auto', undef, 'copy', undef); | |
44 | +my %flags; | |
36 | 45 | GetOptions( |
37 | - 'info' => sub { $mode = 'info'; }, | |
38 | - 'convert=s' => sub { $mode = 'convert'; $tscfg = $_[1]; }, | |
39 | - 'set' => sub { $mode = 'set'; }, | |
40 | - 'xport=s' => sub { $mode = 'export'; $plain = $_[1]; }, | |
41 | - 'model=s' => \$model, | |
42 | - 'width=i' => \$width, | |
43 | - 'height=i' => \$height, | |
44 | - 'touches=i' => \$touches, | |
45 | - 'flags=s' => \$flags, | |
46 | - '1' => sub { $format = 'plain' }, | |
47 | - '2' => sub { $format = 'tscfg' }, | |
48 | - '3' => sub { $format = 'scrambled' }, | |
46 | + 'read' => sub { $readwrite = 0; }, | |
47 | + 'write' => sub { $readwrite = 1; }, | |
48 | + 'f|iformat=s' => \$iformat, | |
49 | + 'ifile=s' => \$ifile, | |
50 | + 'g|oformat=s' => \$oformat, | |
51 | + 'ofile=s' => \$ofile, | |
52 | + 'set=s%' => $flags, | |
49 | 53 | ) or exit usage; |
50 | 54 | |
51 | -my $fwfile = $ARGV[0] or exit usage; | |
55 | +defined $ifile or exit usage; | |
52 | 56 | |
53 | -sub set_params { | |
54 | - my ($rep) = @_; | |
55 | - if (defined $model) { | |
56 | - $rep->set_model($model); | |
57 | - } | |
58 | - if (defined $width) { | |
59 | - $rep->set_width($width); | |
60 | - } | |
61 | - if (defined $height) { | |
62 | - $rep->set_height($height); | |
63 | - } | |
64 | - if (defined $touches) { | |
65 | - $rep->set_touches($touches); | |
66 | - } | |
67 | - if (defined $flags) { | |
68 | - for my $flag (split /,\s*/, $flags) { | |
69 | - if ($flag =~ /^(no)?xflip$/) { | |
70 | - $rep->set_xmirrored($flag !~ /^no/); | |
71 | - } elsif ($flag =~ /^(no)?yflip$/) { | |
72 | - $rep->set_ymirrored($flag !~ /^no/); | |
73 | - } elsif ($flag =~ /^(no)?swap$/) { | |
74 | - $rep->set_swapped($flag !~ /^no/); | |
75 | - } elsif ($flag =~ /^(no)?track$/) { | |
76 | - $rep->set_tracking($flag !~ /^no/); | |
77 | - } else { | |
78 | - warn "Invalid flag: $flag"; | |
79 | - } | |
80 | - } | |
57 | +print "Loading $ifile...\n"; | |
58 | +my $rep = Firmware::Silead->load_as($ifile, $iformat); | |
59 | +if (!defined($rep)) { | |
60 | + if ($iformat eq 'auto') { | |
61 | + die "Can't autodetect format of $ifile - is this really a firmware image?"; | |
62 | + } else { | |
63 | + die "Invalid input - can't load $ifile as type $iformat (or $iformat is not a valid format)"; | |
81 | 64 | } |
82 | 65 | } |
83 | 66 | |
84 | -if ($mode eq 'info') { | |
85 | - print "Loading $fwfile...\n"; | |
86 | - my $rep = Firmware::Silead->load($fwfile) or die "Can't load firmware $fwfile: $@"; | |
67 | +if (!$readwrite) { | |
87 | 68 | print "Controller model: " . $rep->model . "\n"; |
88 | 69 | print "Panel width: " . $rep->width . "\n"; |
89 | 70 | print "Panel height: " . $rep->height . "\n"; |
@@ -99,45 +80,29 @@ if ($mode eq 'info') { | ||
99 | 80 | printf " %02x", $page; |
100 | 81 | } |
101 | 82 | print "\n"; |
102 | -} elsif ($mode eq 'set') { | |
103 | - print "Loading $fwfile...\n"; | |
104 | - my $rep = Firmware::Silead->load($fwfile) or die "Can't load firmware $fwfile: $@"; | |
105 | - print "Setting parameters...\n"; | |
106 | - set_params($rep); | |
107 | - print "Saving $fwfile...\n"; | |
108 | - $rep->save($fwfile); | |
109 | -} elsif ($mode eq 'convert') { | |
110 | - print "Loading $tscfg...\n"; | |
111 | - my $data; | |
112 | - do { | |
113 | - my $in = IO::File->new($tscfg, 'r') or die "Can't open $tscfg: $!"; | |
114 | - $in->binmode; | |
115 | - local $/ = undef; | |
116 | - $data = <$in>; | |
117 | - defined($data) or die "Can't load firmware: $!"; | |
118 | - $in->close(); | |
119 | - }; | |
120 | - | |
121 | - my $rep = Firmware::Silead->new(); | |
122 | - if ($format eq 'plain') { | |
123 | - $rep->import_fw($data) or die "Can't parse firmware: $@"; | |
124 | - } elsif ($format eq 'tscfg') { | |
125 | - $rep->import_tscfg($data) or die "Can't parse firmware: $@"; | |
126 | - } elsif ($format eq 'scrambled') { | |
127 | - $rep->import_scrambled($data) or die "Can't parse firmware: $@"; | |
83 | +} | |
84 | + | |
85 | +if ($readwrite) { | |
86 | + print "Setting parameters...\n" unless !int %flags; | |
87 | + for my $key (keys(%flags)) { | |
88 | + $rep->set_param($key, $flags{$key}); | |
128 | 89 | } |
129 | - | |
130 | - print "Setting parameters...\n"; | |
131 | - set_params($rep); | |
132 | 90 | |
133 | - print "Saving $fwfile...\n"; | |
134 | - $rep->save($fwfile) or die "Can't write firmware: $@"; | |
135 | -} elsif ($mode eq 'export') { | |
136 | - print "Loading $fwfile...\n"; | |
137 | - my $rep = Firmware::Silead->load($fwfile) or die "Can't load firmware $fwfile: $@"; | |
138 | - print "Exporting to $plain...\n"; | |
139 | - my $out = IO::File->new($plain, 'w') or die "Can't open $plain: $!"; | |
140 | - my $data = $rep->export_fw(); | |
141 | - $out->print($data) or die "Can't write firmware: $!"; | |
142 | - $out->close(); | |
91 | + if ($oformat eq 'copy') { | |
92 | + # TODO does not work for auto, implement better detection api | |
93 | + $oformat = $iformat; | |
94 | + } | |
95 | + print "Saving $ofile...\n"; | |
96 | + if (!$rep->save_as($ofile, $oformat)) { | |
97 | + die "Error saving to $ofile"; | |
98 | + } | |
143 | 99 | } |
100 | + | |
101 | +do { | |
102 | + my $in = IO::File->new($tscfg, 'r') or die "Can't open $tscfg: $!"; | |
103 | + $in->binmode; | |
104 | + local $/ = undef; | |
105 | + $data = <$in>; | |
106 | + defined($data) or die "Can't load firmware: $!"; | |
107 | + $in->close(); | |
108 | +}; |