• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Firmware of Silead Touchscreen Controller for Jumper EZpad 6 Pro.


Commit MetaInfo

Revisionfdc895d636cc81641342c8bbe5e117b75edd3021 (tree)
Zeit2017-04-19 15:31:44
AutorGregor Riepl <onitake@gmai...>
CommiterGregor Riepl

Log Message

WIP rewrite of fwtool and the Perl lib

Ändern Zusammenfassung

Diff

--- a/tools/Firmware/Silead.pm
+++ b/tools/Firmware/Silead.pm
@@ -2,11 +2,58 @@ package Firmware::Silead;
22
33 use strict;
44 use IO::File;
5+use IO::Scalar;
56
67 our $MAGIC = 'GSLX';
78 our $FORMAT = 1;
89 our $HEADER_SIZE = 24;
910 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+};
1057
1158 sub _unpack_header {
1259 my ($header) = @_;
@@ -40,18 +87,50 @@ sub new {
4087 xmirrored => 0,
4188 ymirrored => 0,
4289 tracking => 0,
43- }, ref $class ? ref $class : $class;
90+ format => undef,
91+ config => [ (0) x 512 ],
92+ }, ref $class || $class;
4493 }
4594
4695 sub load {
47- my ($class, $handle) = @_;
96+ my ($class, $handle, $type) = @_;
4897 if (!ref $handle) {
4998 $handle = IO::File->new($handle, 'r');
5099 }
51100 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";
53128 return undef;
54129 }
130+}
131+
132+sub load_new {
133+ my ($self, $handle) = @_;
55134 binmode $handle;
56135 read $handle, my $header, $HEADER_SIZE;
57136 my ($magic, $model, $format, $touches, $width, $height, $swapped, $xmirrored, $ymirrored, $tracking, $pages) = _unpack_header $header;
@@ -63,17 +142,16 @@ sub load {
63142 $@ = "Invalid file format $format";
64143 return undef;
65144 }
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 ];
77155 for (my $i = 0; $i < $pages; $i++) {
78156 read $handle, my $buffer, $PAGE_SIZE;
79157 my ($address, $size, $data) = _unpack_page $buffer;
@@ -81,11 +159,12 @@ sub load {
81159 return undef;
82160 }
83161 }
162+ $self->{format} = 'new';
84163 return $self;
85164 }
86165
87166 sub save {
88- my ($self, $handle) = @_;
167+ my ($self, $handle, $type) = @_;
89168 if (!ref $handle) {
90169 $handle = IO::File->new($handle, 'w');
91170 }
@@ -93,6 +172,22 @@ sub save {
93172 $@ = "Invalid file handle";
94173 return 0;
95174 }
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) = @_;
96191 binmode $handle;
97192 my @pages = $self->get_pages;
98193 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 {
106201 }
107202
108203 sub unpack {
109- my ($class, $data) = @_;
204+ my ($self, $data) = @_;
205+ if (!ref $self) {
206+ $self = $self->new();
207+ }
110208 my $header = substr $data, 0, $HEADER_SIZE;
111209 my ($magic, $model, $format, $touches, $width, $height, $swapped, $xmirrored, $ymirrored, $tracking, $pages) = _unpack_header $header;
112210 if ($magic ne $MAGIC) {
@@ -117,17 +215,16 @@ sub unpack {
117215 $@ = "Invalid file format $format";
118216 return undef;
119217 }
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 ];
131228 for (my $i = 0; $i < $pages; $i++) {
132229 my $buffer = substr $HEADER_SIZE + $i * $PAGE_SIZE, $PAGE_SIZE;
133230 my ($address, $size, $data) = _unpack_page $buffer ;
@@ -152,37 +249,101 @@ sub pack {
152249 return $data;
153250 }
154251
155-sub import_scrambled {
252+sub load_win {
156253 my ($self, $input) = @_;
157254 my $tscfg = '';
158255 for my $byte (split //, $input) {
159256 my $descrambled = chr(ord($byte) ^ 0x88);
160257 $tscfg .= $descrambled;
161258 }
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;
163272 }
164273
165-sub import_tscfg {
274+sub load_header {
166275 my ($self, $input) = @_;
167276 my ($cfg, $fw) = (0, '');
277+ my @config;
168278 for my $line (split /\n/, $input) {
169- if ($cfg and $line =~ /};/) {
279+ if ($cfg > 0 and $line =~ /};/) {
170280 $cfg = 0;
171281 }
172282 if ($line =~ /TS_CFG_DATA|GSLX68X_FW/) {
173283 $cfg = 1;
174284 }
175- if ($cfg) {
285+ if ($cfg == 0 and $line =~ /gsl_config_data_id/) {
286+ $cfg = 2;
287+ }
288+ if ($cfg == 1) {
176289 $line =~ s/\s//g;
177- $line = lc($line);
290+ $line = lc $line;
178291 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;
181294 $fw .= pack '(LL)<', $address, $data;
182295 }
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;
183342 }
184343 }
185- return $self->import_fw($fw);
344+ $tscfg .= "\n";
345+ $tscfg .= "};\n";
346+ return $tscfg;
186347 }
187348
188349 sub import_fw {
--- a/tools/fwtool
+++ b/tools/fwtool
@@ -9,81 +9,62 @@ use lib dirname (__FILE__);
99 use Firmware::Silead;
1010
1111 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";
3240 -1;
3341 }
3442
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;
3645 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,
4953 ) or exit usage;
5054
51-my $fwfile = $ARGV[0] or exit usage;
55+defined $ifile or exit usage;
5256
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)";
8164 }
8265 }
8366
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) {
8768 print "Controller model: " . $rep->model . "\n";
8869 print "Panel width: " . $rep->width . "\n";
8970 print "Panel height: " . $rep->height . "\n";
@@ -99,45 +80,29 @@ if ($mode eq 'info') {
9980 printf " %02x", $page;
10081 }
10182 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});
12889 }
129-
130- print "Setting parameters...\n";
131- set_params($rep);
13290
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+ }
14399 }
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+};