1 #!perl -w |
|
2 # |
|
3 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 # All rights reserved. |
|
5 # This component and the accompanying materials are made available |
|
6 # under the terms of the License "Eclipse Public License v1.0" |
|
7 # which accompanies this distribution, and is available |
|
8 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
9 # |
|
10 # Initial Contributors: |
|
11 # Nokia Corporation - initial contribution. |
|
12 # |
|
13 # Contributors: |
|
14 # |
|
15 # Description: |
|
16 # |
|
17 use strict; |
|
18 |
|
19 # |
|
20 # A simple class to manage feature flags for a feature set data file. |
|
21 # |
|
22 package HCRrec; |
|
23 |
|
24 my %typemap = ( |
|
25 Int32 => 0x00000001, |
|
26 Int16 => 0x00000002, |
|
27 Int8 => 0x00000004, |
|
28 Bool => 0x00000008, |
|
29 UInt32 => 0x00000010, |
|
30 UInt16 => 0x00000020, |
|
31 UInt8 => 0x00000040, |
|
32 LinAddr => 0x00000100, |
|
33 BinData => 0x00010000, |
|
34 Text8 => 0x00020000, |
|
35 ArrayInt32 => 0x00040000, |
|
36 ArrayUInt32 => 0x00080000, |
|
37 Int64 => 0x01000000, |
|
38 UInt64 => 0x02000000, |
|
39 ); |
|
40 my %maptype = reverse %typemap; |
|
41 my %lsdtype2packmap = ( |
|
42 0x00010000 => "C", |
|
43 0x00020000 => "a", |
|
44 0x01000000 => "C", |
|
45 0x02000000 => "C", |
|
46 ); |
|
47 |
|
48 # Create a feature flag object. |
|
49 sub new |
|
50 { |
|
51 my $arg = shift; |
|
52 my $class = ref($arg) || $arg; |
|
53 |
|
54 my $self = { |
|
55 cuid => 0, # 4 bytes |
|
56 eid => 0, # 4 bytes |
|
57 type => 0, # 4 bytes |
|
58 flagword => 0x0000, # 2 bytes |
|
59 valueset => 0, |
|
60 |
|
61 intvalue => 0, # 4 bytes |
|
62 strvalue => "", # array of chars |
|
63 binvalue => [], # array of bytes |
|
64 arrvalue => [], # array of 4 byte integers |
|
65 |
|
66 endian => "LE", |
|
67 }; |
|
68 |
|
69 bless $self, $class; |
|
70 return $self; |
|
71 } |
|
72 |
|
73 sub Endian |
|
74 { |
|
75 my $self = shift; |
|
76 return undef unless(ref($self)); |
|
77 my $arg = shift; |
|
78 return $self->{endian} unless(defined($arg) and $arg =~ m/(^BE$|^LE$)/i); |
|
79 $self->{endian} = lc($1); |
|
80 return $self->{endian}; |
|
81 } |
|
82 |
|
83 # Return a twelve byte string 'feature flag' information. |
|
84 sub GetRecHdrBinary |
|
85 { |
|
86 my $self = shift; |
|
87 return undef unless(ref($self)); |
|
88 |
|
89 my $lsd_size = shift; |
|
90 |
|
91 my $stype = $self->Type(); |
|
92 my @hdrarr = ( $self->CUID(), $self->EID(), $stype, $self->Flags(), |
|
93 $self->SizeInBytes() ); |
|
94 |
|
95 # Decide whether we want big or little endian output. |
|
96 # According to the documentation, 'V', 'N' are GUARANTEED to be 32-bit. |
|
97 my $packstring; |
|
98 if($self->Endian() eq "BE") { |
|
99 $packstring = "N3n2N"; |
|
100 } |
|
101 else { |
|
102 $packstring = "V3v2V"; # Little endian. |
|
103 } |
|
104 |
|
105 # |
|
106 # Could add range checks here for 8-bit and 16-bit types. |
|
107 # However would stop negative test cases from being generated. |
|
108 # Do it later. |
|
109 # |
|
110 |
|
111 if ($stype & 0xffff) { |
|
112 print "Writing integer\n" if ($mhd::otrace); |
|
113 push @hdrarr, $self->IntValue(); |
|
114 } |
|
115 |
|
116 if ($stype & 0xffff0000) { |
|
117 if ($self->Length() > 0) { |
|
118 print "Writing offset: " . $lsd_size . "\n" if ($mhd::otrace); |
|
119 push @hdrarr, $lsd_size; |
|
120 } |
|
121 else { |
|
122 print "Writing null offset: 0\n" if ($mhd::otrace); |
|
123 push @hdrarr, 0; |
|
124 } |
|
125 } |
|
126 |
|
127 my $hdr_string = pack $packstring, @hdrarr; |
|
128 |
|
129 return $hdr_string; |
|
130 } |
|
131 |
|
132 # Return a twelve byte string 'feature flag' information. |
|
133 # Assumes Little Endian output! |
|
134 sub GetRecLsdBinary |
|
135 { |
|
136 my $self = shift; |
|
137 return undef unless(ref($self)); |
|
138 |
|
139 my $value = ""; |
|
140 my $valuelen = $self->Length(); |
|
141 my $vallen = $valuelen; |
|
142 #print "vallen before:" . $vallen . "\n"; |
|
143 $vallen = ($valuelen+3)&0xfffc if ($valuelen%4) ; |
|
144 #print "vallen after:" . $vallen . "\n"; |
|
145 my $valtype = $self->{type}; |
|
146 |
|
147 # String |
|
148 if ($valtype & 0x00020000) { |
|
149 my $packstr = $lsdtype2packmap{$valtype} . $vallen; |
|
150 printf ("packstr:%s\n", $packstr) if($mhd::otrace); |
|
151 printf ("strvalue:%s\n", $self->{strvalue}) if($mhd::otrace); |
|
152 $value = pack $packstr, $self->{strvalue} ; |
|
153 } |
|
154 # Binary Data |
|
155 elsif ($valtype & 0x00010000) { |
|
156 for (my $c=0; $c < $valuelen; $c++) { |
|
157 my $byte = $self->{binvalue}[$c]; |
|
158 $value .= pack $lsdtype2packmap{$valtype}, $byte; |
|
159 $vallen--; |
|
160 } |
|
161 while ($vallen > 0) { |
|
162 $value .= pack "C", ( 0x00 ); |
|
163 $vallen--; |
|
164 } |
|
165 } |
|
166 # 64bit quantity |
|
167 elsif ($valtype & 0x03000000) { |
|
168 die "error: 64 bit integer missing hex binvalues\n" if (! exists $self->{binvalue}[7]); |
|
169 $value = pack $lsdtype2packmap{$valtype}, $self->{binvalue}[0]; |
|
170 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[1]; |
|
171 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[2]; |
|
172 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[3]; |
|
173 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[4]; |
|
174 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[5]; |
|
175 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[6]; |
|
176 $value .= pack $lsdtype2packmap{$valtype}, $self->{binvalue}[7]; |
|
177 } |
|
178 # array of 32bit quantity |
|
179 elsif ($valtype & 0x000C0000) { |
|
180 for (my $c=0; $c < $valuelen; $c++) { |
|
181 my $int = $self->{arrvalue}[$c]; |
|
182 $value .= pack "V", $int; |
|
183 $vallen--; |
|
184 } |
|
185 } |
|
186 else { |
|
187 die "panic: proramming error!!"; |
|
188 } |
|
189 |
|
190 return $value; |
|
191 } |
|
192 |
|
193 # A single 32-bit number. |
|
194 sub CUID |
|
195 { |
|
196 my $self = shift; |
|
197 return undef unless(ref($self)); |
|
198 my $uid = shift; |
|
199 return $self->{cuid} unless(defined($uid)); |
|
200 my $uidv = hex($uid); |
|
201 $self->{cuid} = $uidv; |
|
202 return $uidv; |
|
203 } |
|
204 |
|
205 # A single 32-bit number. |
|
206 sub EID |
|
207 { |
|
208 my $self = shift; |
|
209 return undef unless(ref($self)); |
|
210 my $id = shift; |
|
211 return $self->{eid} unless(defined($id)); |
|
212 my $idv = int($id); |
|
213 $self->{eid} = $idv; |
|
214 return $idv; |
|
215 } |
|
216 |
|
217 sub Type |
|
218 { |
|
219 my $self = shift; |
|
220 return undef unless(ref($self)); |
|
221 my $type = shift; |
|
222 return $self->{type} unless(defined($type)); |
|
223 my $enum = $typemap{$type}; |
|
224 #print "--->Defined\n" if (defined $enum); |
|
225 #print "--->NOT Defined\n" if (! defined $enum); |
|
226 die "error: unknown setting type found in input file\n" if (! defined $enum); |
|
227 $self->{type} = $enum; |
|
228 return $enum; |
|
229 } |
|
230 |
|
231 sub TypeName |
|
232 { |
|
233 my $self = shift; |
|
234 return undef unless(ref($self)); |
|
235 return "Undefined Type" if (! exists $maptype{$self->{type}}); |
|
236 return $maptype{$self->{type}}; |
|
237 } |
|
238 |
|
239 sub Flags |
|
240 { |
|
241 my $self = shift; |
|
242 return undef unless(ref($self)); |
|
243 my $flags = shift; |
|
244 return $self->{flagword} unless(defined($flags)); |
|
245 my $vf = hex($flags); |
|
246 $self->{flagword} = $vf; |
|
247 return $vf; |
|
248 } |
|
249 |
|
250 sub Length |
|
251 { |
|
252 my $self = shift; |
|
253 return undef unless(ref($self)); |
|
254 my $len = shift; |
|
255 die "panic: Length() does not take an argument!\n" if (defined($len)); |
|
256 |
|
257 my $length = 0; |
|
258 if ($self->{type} & 0x00020000) { |
|
259 $length = length ($self->{strvalue}); |
|
260 } |
|
261 elsif ($self->{type} & 0x03010000) { |
|
262 my $array_ref = $self->{binvalue}; |
|
263 my @array = @$array_ref; |
|
264 $length = $#array+1; |
|
265 } |
|
266 elsif ($self->{type} & 0x000C0000) { |
|
267 my $array_ref = $self->{arrvalue}; |
|
268 my @array = @$array_ref; |
|
269 $length = $#array+1; |
|
270 #printf ("arrval length %d %d\n", length ($self->{arrval}), $length); |
|
271 } |
|
272 else { |
|
273 $length = 0; |
|
274 } |
|
275 return $length; |
|
276 } |
|
277 |
|
278 sub SizeInBytes |
|
279 { |
|
280 my $self = shift; |
|
281 return undef unless(ref($self)); |
|
282 my $len = shift; |
|
283 die "panic: Length() does not take an argument!\n" if (defined($len)); |
|
284 |
|
285 my $size = 0; |
|
286 if ($self->{type} & 0x00020000) { |
|
287 $size = length ($self->{strvalue}); |
|
288 } |
|
289 elsif ($self->{type} & 0x03010000) { |
|
290 my $array_ref = $self->{binvalue}; |
|
291 my @array = @$array_ref; |
|
292 $size = $#array+1; |
|
293 } |
|
294 elsif ($self->{type} & 0x000C0000) { |
|
295 my $array_ref = $self->{arrvalue}; |
|
296 my @array = @$array_ref; |
|
297 $size = ($#array+1)*4; |
|
298 #printf ("arrval length %d %d\n", length ($self->{arrval}), $length); |
|
299 } |
|
300 else { |
|
301 $size = 0; |
|
302 } |
|
303 return $size; |
|
304 } |
|
305 |
|
306 sub IsValid |
|
307 { |
|
308 my $self = shift; |
|
309 return undef unless(ref($self)); |
|
310 |
|
311 if (($self->{cuid} == 0) || ($self->{eid} == 0) || |
|
312 ($self->{type} == 0) || ($self->{flagword} != 0) || |
|
313 ($self->IsValueSet() == 0)) { |
|
314 return 0; |
|
315 } |
|
316 |
|
317 #Record valid if we reach here |
|
318 return 1; |
|
319 } |
|
320 |
|
321 sub IsValueSet |
|
322 { |
|
323 my $self = shift; |
|
324 return undef unless(ref($self)); |
|
325 return $self->{valueset}; |
|
326 } |
|
327 |
|
328 sub MarkValueSet |
|
329 { |
|
330 my $self = shift; |
|
331 return undef unless(ref($self)); |
|
332 $self->{valueset} = 1; |
|
333 } |
|
334 |
|
335 sub IntValue |
|
336 { |
|
337 my $self = shift; |
|
338 return undef unless(ref($self)); |
|
339 my $value = shift; |
|
340 if (defined($value)) { |
|
341 my $int = int($value); |
|
342 $self->{intvalue} = $int; |
|
343 $self->MarkValueSet(); |
|
344 } |
|
345 return $self->{intvalue}; |
|
346 } |
|
347 |
|
348 sub HexValue |
|
349 { |
|
350 my $self = shift; |
|
351 return undef unless(ref($self)); |
|
352 my $value = shift; |
|
353 return $self->{intvalue} unless(defined($value)); |
|
354 my $int = hex($value); |
|
355 $self->{intvalue} = $int; |
|
356 $self->MarkValueSet(); |
|
357 return $int; |
|
358 } |
|
359 |
|
360 sub StrValue |
|
361 { |
|
362 my $self = shift; |
|
363 return undef unless(ref($self)); |
|
364 my $value = shift; |
|
365 return $self->{strvalue} unless(defined($value)); |
|
366 #printf ("strlen before %d\n", length ($self->{strvalue})); |
|
367 $self->{strvalue} .= $value; |
|
368 #printf ("strlen after %d\n", length ($self->{strvalue})); |
|
369 $self->MarkValueSet(); |
|
370 return $value; |
|
371 } |
|
372 |
|
373 sub ArrValue |
|
374 { |
|
375 my $self = shift; |
|
376 return undef unless(ref($self)); |
|
377 my $value = shift; |
|
378 |
|
379 return $self->{arrvalue} unless(defined($value)); |
|
380 |
|
381 my $int = int($value); |
|
382 my $index = $self->Length(); |
|
383 |
|
384 $self->{arrvalue}[$index] = $int; # Increments the array size as well as appending item |
|
385 $index*=4; |
|
386 |
|
387 printf ("warning: array value larger than HCR maximum (512 bytes): %d\n", $index) if ($index > 512); |
|
388 $self->MarkValueSet(); |
|
389 |
|
390 return $self->{arrvalue}; |
|
391 } |
|
392 |
|
393 sub BinValue |
|
394 { |
|
395 my $self = shift; |
|
396 return undef unless(ref($self)); |
|
397 my $value = shift; |
|
398 |
|
399 return $self->{binvalue} unless(defined($value)); |
|
400 |
|
401 my @hwords = split(/\s/,$value); |
|
402 shift @hwords if ($hwords[0] eq ""); |
|
403 my $hwordslen = scalar(@hwords); |
|
404 |
|
405 #printf("(len:%d)(0:%04x 1:%04x last:%04x)\n", $hwordslen, hex($hwords[0]), hex($hwords[1]), hex($hwords[$hwordslen-1])) if ($mhd::trace); |
|
406 |
|
407 my $index = $self->Length(); |
|
408 #printf ("binlen before %d\n", $index); |
|
409 |
|
410 #print "Index: " . $index . "\n"; |
|
411 foreach my $word (@hwords) { |
|
412 if (length ($word) == 2) { |
|
413 $self->{binvalue}[$index] = hex($word); |
|
414 } |
|
415 else { |
|
416 die "error: hexadecimal value '$word' too short/large for 8-bit integer\n"; |
|
417 } |
|
418 |
|
419 |
|
420 #$self->{binvalue}[$index] = $mint; |
|
421 #printf("%d: %04x\n", $count, $self->{binvalue}[$count]); |
|
422 $index++; |
|
423 } |
|
424 |
|
425 |
|
426 #printf ("binlen after %d\n", $index); |
|
427 |
|
428 printf ("warning: binary value larger than HCR maximum (512 bytes): %d\n", $index) if ($index > 512); |
|
429 $self->MarkValueSet(); |
|
430 return $self->{binvalue}; |
|
431 } |
|
432 |
|
433 |
|
434 # ########################################################################### |
|
435 |
|
436 1; |
|
437 |
|