ruby-amt 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +1 -0
- data/COPYING +15 -0
- data/ChangeLog +392 -0
- data/GPL +674 -0
- data/Rakefile +292 -0
- data/VERSION +1 -0
- data/doc/default.css +211 -0
- data/doc/default.template +78 -0
- data/doc/documentation.page +40 -0
- data/doc/img/bg.jpg +0 -0
- data/doc/img/image.jpg +0 -0
- data/doc/img/line.jpg +0 -0
- data/doc/img/shadow.jpg +0 -0
- data/doc/index.page +61 -0
- data/doc/installation.page +115 -0
- data/doc/news.page +25 -0
- data/doc/news/release_0_1_0.page +16 -0
- data/doc/virtual +2 -0
- data/lib/amt/pt_status.rb +59 -0
- data/lib/amt/service.rb +16 -0
- data/lib/amt/service/basic.rb +159 -0
- data/lib/amt/service/hardware_asset.rb +83 -0
- data/lib/amt/service/hardware_asset/amt_information_table.rb +49 -0
- data/lib/amt/service/hardware_asset/asset.rb +118 -0
- data/lib/amt/service/hardware_asset/baseboard.rb +31 -0
- data/lib/amt/service/hardware_asset/bios.rb +65 -0
- data/lib/amt/service/hardware_asset/computer_system.rb +30 -0
- data/lib/amt/service/hardware_asset/fru.rb +37 -0
- data/lib/amt/service/hardware_asset/media_device.rb +63 -0
- data/lib/amt/service/hardware_asset/memory_module.rb +91 -0
- data/lib/amt/service/hardware_asset/portable_battery.rb +80 -0
- data/lib/amt/service/hardware_asset/processor.rb +123 -0
- data/lib/amt/service/hardware_asset/vpro_verification_table.rb +120 -0
- data/lib/amt/service/network_administration.rb +181 -0
- data/lib/amt/service/network_administration/structures.rb +29 -0
- data/lib/amt/service/remote_control.rb +73 -0
- data/lib/amt/service/remote_control/structures.rb +120 -0
- data/lib/amt/service/security_administration.rb +430 -0
- data/lib/amt/service/security_administration/structures.rb +117 -0
- data/lib/amt/system.rb +134 -0
- data/lib/amt/utility.rb +33 -0
- data/lib/amt/utility/bit_struct.rb +164 -0
- data/lib/amt/utility/enum.rb +119 -0
- data/lib/amt/version.rb +8 -0
- data/setup.rb +1585 -0
- metadata +125 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'amt/service/security_administration'
|
4
|
+
require 'amt/utility'
|
5
|
+
|
6
|
+
module AMT
|
7
|
+
module Service
|
8
|
+
class SecurityAdministration
|
9
|
+
|
10
|
+
# Enumeration containing names of AMT interfaces that can be enabled/disabled. Used for
|
11
|
+
# SecurityAdministration#set_enabled_interfaces and
|
12
|
+
# SecurityAdministration#get_enabled_interfaces.
|
13
|
+
class EnabledInterface < AMT::Utility::Enum
|
14
|
+
multi_add %w[WebUI SerialOverLAN IdeRedirection]
|
15
|
+
end
|
16
|
+
|
17
|
+
# The AMT SOAP interface enumeration. Used for SecurityAdministration#set_tls_options
|
18
|
+
# and SecurityAdministration#get_tls_options.
|
19
|
+
class Interface < AMT::Utility::Enum
|
20
|
+
multi_add %w[NetworkInterface LocalHostInterface]
|
21
|
+
end
|
22
|
+
|
23
|
+
# The TLS Authentication method enumeration. Used for SecurityAdministration#set_tls_options
|
24
|
+
# and SecurityAdministration#get_tls_options.
|
25
|
+
class TlsAuthentication < AMT::Utility::Enum
|
26
|
+
multi_add %w[NoAuth ServerAuth MutualAuth]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Struct class containing version information as returned by
|
30
|
+
# SecurityAdministration#get_core_version.
|
31
|
+
CoreVersion = Struct.new(:major, :minor, :micro)
|
32
|
+
|
33
|
+
# Mapping of provisioning mode name to value. Used for SecurityAdministration#unprovision and
|
34
|
+
# SecurityAdministration#get_provisioning_mode.
|
35
|
+
class ProvisioningMode < AMT::Utility::Enum
|
36
|
+
multi_add(0 => :current, 1 => :enterprise, 2 => :small_business, 3 => :remote_connectivity)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Struct class containing information about an user ACL. The +user+ field may either contain a
|
40
|
+
# binary String identifying a Kerberos SID or a User class instance, the +access_permission+
|
41
|
+
# field contains an instance of AccessPermission and +realms+ contains a list of UserAclRealm
|
42
|
+
# instances. Used for SecurityAdministration#add_user_acl_entry_ex and
|
43
|
+
# SecurityAdministration#update_user_acl_entry_ex.
|
44
|
+
UserAclEntryEx = Struct.new(:user, :access_permission, :realms)
|
45
|
+
|
46
|
+
# Class containing information about a user. Either a plain text password or an already hashed
|
47
|
+
# password must be provided. If a plain text password is provided, the hashed password is
|
48
|
+
# automatically calculated.
|
49
|
+
class User
|
50
|
+
|
51
|
+
# The username to be used. May only contain 7-bit ASCII characters, in the range of 33- 126,
|
52
|
+
# excluding ‘:’, ‘,’, ‘<’, ‘>’, ‘&’, and ‘”’ characters. Length is limited to 16 characters.
|
53
|
+
attr_reader :username
|
54
|
+
|
55
|
+
# The password for the user. This or #hashed_password must be set.
|
56
|
+
attr_reader :password
|
57
|
+
|
58
|
+
# The hashed password for the user. This or #password must be set.
|
59
|
+
attr_reader :hashed_password
|
60
|
+
|
61
|
+
|
62
|
+
# Create a new User object with the given +username+ and, optionally, +password+.
|
63
|
+
def initialize(username, password = nil)
|
64
|
+
self.username = username
|
65
|
+
self.password = password
|
66
|
+
end
|
67
|
+
|
68
|
+
# Contains the characters that are allowed in the username.
|
69
|
+
ALLOWED_USERNAME_CHARS = (33..126).to_a - ":,<>&\"".unpack('c*')
|
70
|
+
|
71
|
+
# Set the username to +value+. If the username is not valid, an ArgumentError is raised.
|
72
|
+
def username=(value)
|
73
|
+
value.each_byte do |b|
|
74
|
+
ALLOWED_USERNAME_CHARS.include?(b) || raise(ArgumentError, "invalid character in username")
|
75
|
+
end
|
76
|
+
raise(ArgumentError, 'username length is limited to 16 characters') if value.length > 16
|
77
|
+
raise(ArgumentError, 'username must not be empty') if value.length == 0
|
78
|
+
@username = value
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set the #password to +value+ and clear the #hashed_password.
|
82
|
+
def password=(value)
|
83
|
+
@hashed_password, @password = nil, value
|
84
|
+
end
|
85
|
+
|
86
|
+
# Set the #hashed_password to +value+ and clear the #password.
|
87
|
+
def hashed_password=(value)
|
88
|
+
@password, @hashed_password = nil, value
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# Access permissions enumeration. Used in the UserAclEntryEx structure.
|
94
|
+
class AccessPermission < AMT::Utility::Enum
|
95
|
+
multi_add %w[LocalAccessPermission NetworkAccessPermission AnyAccessPermission]
|
96
|
+
end
|
97
|
+
|
98
|
+
# The user ACL realms enumeration. Used in the UserAclEntryEx structure.
|
99
|
+
class UserAclRealm < AMT::Utility::Enum
|
100
|
+
multi_add(0 => :invalid, 1 => :rcs, 2 => :redirection, 3 => :pt_administration,
|
101
|
+
4 => :hardware_asset, 5 => :remote_control, 6 => :storage,
|
102
|
+
7 => :event_manager, 8 => :storage_admin, 9 => :agent_presence_local,
|
103
|
+
10 => :agent_presence_remote, 11 => :circuit_breaker, 12 => :network_time,
|
104
|
+
13 => :general_info, 14 => :firmware_update, 15 => :eit, 16 => :local_un,
|
105
|
+
17 => :endpoint_access_control, 18 => :endpoint_access_control_admin,
|
106
|
+
19 => :event_log_reader, 20 => :security_audit_log, 21 => :user_access_control,
|
107
|
+
22 => :reserved, 23 => :anti_theft)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Struct class containing the fields for a global power policy (used by
|
111
|
+
# SecurityAdministration#set_global_power_policy and
|
112
|
+
# SecurityAdministration#get_global_power_policy).
|
113
|
+
GlobalPowerPolicy = Struct.new(:idle_wake_timeout)
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/amt/system.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# This is the API documentation for ruby-amt!
|
5
|
+
#
|
6
|
+
# Have a look at the \AMT module which provides a good starting point!
|
7
|
+
|
8
|
+
|
9
|
+
#
|
10
|
+
# The ruby-amt library provides access to the SOAP services provided by Intel AMT devices. Before
|
11
|
+
# you decide whether to use the library or not, you should know the following:
|
12
|
+
#
|
13
|
+
# * The library has been designed to be used with Intel AMT 5.0 devices. This is the reason why no
|
14
|
+
# deprecated methods have been implemented.
|
15
|
+
#
|
16
|
+
# * Furthermore, the library has been designed to be used with Intel AMT devices in SMB mode. So
|
17
|
+
# SOAP methods which are only useful for devices in Enterprise Mode have not been implemented. One
|
18
|
+
# reason is that I don't have access to devices in Enterprise Mode and therefore cannot test these
|
19
|
+
# methods.
|
20
|
+
#
|
21
|
+
# = Short Overview
|
22
|
+
#
|
23
|
+
# The library provides a "low-level" implementation of the client side of the SOAP services (as
|
24
|
+
# classes in AMT::Service) as well as a class (AMT::System) for high-level access. The adjective
|
25
|
+
# "low-level" is not really correct since the implementation of the client side of the SOAP services
|
26
|
+
# is not done by generating code from WSDL files (which normally results in a direct mapping of the
|
27
|
+
# SOAP methods and data structures) but by hand-crafting the code and providing simple but adequate
|
28
|
+
# data structures.
|
29
|
+
#
|
30
|
+
# So, although the SOAP service classes directly represent SOAP services and their methods, their
|
31
|
+
# usage in an application is actually quite simple. However, there are some AMT work flows which
|
32
|
+
# require calling more than one method or getting available states before actually setting
|
33
|
+
# something. This can easily be overlooked by people not acquainted with Intel AMT. Therefore there
|
34
|
+
# exists a class for high-level access to the AMT functionality of a system which takes this burden
|
35
|
+
# of you.
|
36
|
+
#
|
37
|
+
# = Library Organization
|
38
|
+
#
|
39
|
+
# This module houses all modules/classes that are in the ruby-amt library. There are three main
|
40
|
+
# modules/classes:
|
41
|
+
#
|
42
|
+
# [AMT::Service]
|
43
|
+
# This module contains all SOAP service classes. There is a one-to-one mapping from
|
44
|
+
# the Intel AMT SOAP services to classes in this module. Note that not all SOAP services are
|
45
|
+
# implemented because some are not really useful for a management application.
|
46
|
+
#
|
47
|
+
# [AMT::Utility]
|
48
|
+
# This module houses utility classes that are used by other classes (mostly the service classes).
|
49
|
+
#
|
50
|
+
# [AMT::System]
|
51
|
+
# This is the class that can be used for high-level access to the functionality of an AMT system.
|
52
|
+
#
|
53
|
+
# = Library Usage
|
54
|
+
#
|
55
|
+
# == Direct use of SOAP Service Classes
|
56
|
+
#
|
57
|
+
# All service classes are derived from AMT::Service::Basic and have the same initialization
|
58
|
+
# parameters. You need to provide at least the hostname of the AMT device, a username and a
|
59
|
+
# password.
|
60
|
+
#
|
61
|
+
# You don't need to load an individual service class, just use
|
62
|
+
#
|
63
|
+
# require 'amt/service'
|
64
|
+
#
|
65
|
+
# since this will automatically load any service class and any data structures that are needed on
|
66
|
+
# demand.
|
67
|
+
#
|
68
|
+
# For example, the AMT::Service::RemoteControl service can be created like this:
|
69
|
+
#
|
70
|
+
# rcs = AMT::Service::RemoteControl.new('amt.example.com', 'admin', 'P@ssw0rD')
|
71
|
+
#
|
72
|
+
# After that you can just call the method you would like to invoke on the AMT system. But before
|
73
|
+
# that you should read the method description sothat you know what parameters to pass. Since the
|
74
|
+
# SOAP service classes are not created from WSDL files, they provide a nicer, more Ruby like
|
75
|
+
# interface to the SOAP methods. However, this also means that the method signature sometimes
|
76
|
+
# differs a little bit from the method signature as defined in the "Network Interface Guide" (which
|
77
|
+
# can be found in the Intel AMT SDK).
|
78
|
+
#
|
79
|
+
# Take the AMT::Service::RemoteControl#get_system_power_state as example:
|
80
|
+
#
|
81
|
+
# sps = rcs.get_system_power_state
|
82
|
+
#
|
83
|
+
# Since this method takes no parameters, there is no difference in this respect. The method would
|
84
|
+
# nominally return a bit structure as an unsigned 32 bit integer. However, this has been changed
|
85
|
+
# sothat it returns an instance of AMT::Service::RemoteControl::SystemPowerState which provides easy
|
86
|
+
# access to the fields of the bit structure. For example:
|
87
|
+
#
|
88
|
+
# sps.power_state # => :s0
|
89
|
+
# sps.watchdog_expired? # => false
|
90
|
+
# sps.power_source # => :ac
|
91
|
+
#
|
92
|
+
# Such a conversion of input or output arguments is true for all implemented methods. The special
|
93
|
+
# data structures needed by a service are defined in the namespace of the service. For example, all
|
94
|
+
# data structures needed as input or returned as output for the RemoteControl service are defined
|
95
|
+
# unter AMT::Service::RemoteControl.
|
96
|
+
#
|
97
|
+
# So how does one provide input parameters? We take the AMT::Service::RemoteControl#remote_control
|
98
|
+
# method as example. You can learn from the method description that it has one mandatory and several
|
99
|
+
# optional arguments. Additionally, it is stated which type the arguments have. In its simplest
|
100
|
+
# form, one needs to provide just a value for the +command+ parameter which should be an instance of
|
101
|
+
# AMT::Service::RemoteControl::RemoteControlCommand. Checking out the class we see that it is a
|
102
|
+
# subclass of AMT::Utility::Enum. This allows us to use any of the following ways to power up an AMT
|
103
|
+
# system which is currently powered down:
|
104
|
+
#
|
105
|
+
# rcs.remote_control(AMT::Service::RemoteControl::RemoteControlCommand.for(:0x11))
|
106
|
+
# rcs.remote_control(AMT::Service::RemoteControl::RemoteControlCommand.for(:power_up))
|
107
|
+
# rcs.remote_control(0x11)
|
108
|
+
# rcs.remote_control(:power_up)
|
109
|
+
#
|
110
|
+
# As you can see, one doesn't actually need to create an instance of the RemoteControlCommand class,
|
111
|
+
# one just needs to provide either a valid enumeration value or enumeration name! <b>This is true
|
112
|
+
# everywhere a subclass of AMT::Utility::Enum is expected.</b>
|
113
|
+
#
|
114
|
+
# A simliar short-cut is available when an instance of a subclass of AMT::Utility::BitStruct is
|
115
|
+
# expected - see AMT::Utility::BitStruct.new !
|
116
|
+
#
|
117
|
+
# Here is a final example with some optional parameters:
|
118
|
+
#
|
119
|
+
# rcs.remote_control(:power_up, 343, :boot_options => [:lock_keyboard], :special_command => :pxe_boot)
|
120
|
+
#
|
121
|
+
#
|
122
|
+
# == High-level Interface
|
123
|
+
#
|
124
|
+
# The high-level interface is not implemented currently.
|
125
|
+
#
|
126
|
+
module AMT
|
127
|
+
|
128
|
+
# High-level access to AMT functionality.
|
129
|
+
#
|
130
|
+
# NOT IMPLEMENTED
|
131
|
+
class System
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/lib/amt/utility.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module AMT
|
4
|
+
|
5
|
+
# This module houses utility classes that are used by the other AMT classes.
|
6
|
+
module Utility
|
7
|
+
|
8
|
+
autoload :BitStruct, 'amt/utility/bit_struct'
|
9
|
+
autoload :Enum, 'amt/utility/enum'
|
10
|
+
|
11
|
+
|
12
|
+
# Create a UUID string from binary data which can either have a length of 16 characters (then it
|
13
|
+
# is considered to be a binary UUID) or a length of 32 characters (an already unpacked binary
|
14
|
+
# UUID).
|
15
|
+
def self.binary_to_uuid(data)
|
16
|
+
data = data.unpack('H32').first if data.length == 16
|
17
|
+
a = data.scan(/../)
|
18
|
+
a[0,4].reverse.join('') + "-" + a[4,2].reverse.join('') + "-" + a[6,2].reverse.join('') +
|
19
|
+
"-" + a[8,2].join('') + "-" + a[10,6].join('')
|
20
|
+
end
|
21
|
+
|
22
|
+
# Convert a UUID string to binary data.
|
23
|
+
def self.uuid_to_binary(uuid)
|
24
|
+
[uuid[0,8].scan(/../).reverse.join('') +
|
25
|
+
uuid[9,4].scan(/../).reverse.join('') +
|
26
|
+
uuid[14,4].scan(/../).reverse.join('') +
|
27
|
+
uuid[19,4].scan(/../).join('') +
|
28
|
+
uuid[24,12].scan(/../).join('')].pack('H32')
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module AMT
|
4
|
+
|
5
|
+
module Utility
|
6
|
+
|
7
|
+
# A very simple base class which can be used to extract information from a number based on its
|
8
|
+
# bits, or to set it.
|
9
|
+
#
|
10
|
+
# It isn't useful to create objects directly from this class but one should create a subclass
|
11
|
+
# and use the provided class methods to define how to interpret the bits of a number.
|
12
|
+
class BitStruct
|
13
|
+
|
14
|
+
# Interpret the bit with the +index+ (starting from zero) as boolean flag named +name+ (should
|
15
|
+
# be a Symbol). If the bit at the index is +1+, the flag is interpreted as +true+. The
|
16
|
+
# optional parameter +desc+ can be used to provide a textual representation of the +true+
|
17
|
+
# state.
|
18
|
+
#
|
19
|
+
# This method also adds accessor methods for the property. For example, if the property is
|
20
|
+
# called +amt_enabled+, the created getter method is called <tt>#amt_enabled?</tt> and the
|
21
|
+
# setter method is called <tt>#amt_enabled!</tt>. Note the trailing question/exclamation
|
22
|
+
# marks.
|
23
|
+
#
|
24
|
+
# Example usage:
|
25
|
+
#
|
26
|
+
# boolean 5, :amt_enabled, 'AMT is enabled'
|
27
|
+
def self.boolean(index, name, desc = name.to_s)
|
28
|
+
index = (0x1 << index)
|
29
|
+
(@boolean ||= []) << [name, desc]
|
30
|
+
define_method("#{name}?") do
|
31
|
+
@value & index == index
|
32
|
+
end
|
33
|
+
define_method("#{name}!") do
|
34
|
+
@value |= index
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# Same as BitStruct.boolean but +mask+ defines a bit mask and the value is only +true+ if all
|
40
|
+
# bits specified by the bit mask (ie. all bits that are +1+ in the bit mask) are set.
|
41
|
+
#
|
42
|
+
# Example usage:
|
43
|
+
#
|
44
|
+
# mboolean 0b101, :amt_enabled, 'AMT is enabled'
|
45
|
+
def self.mboolean(mask, name, desc = name.to_s)
|
46
|
+
(@boolean ||= []) << [name, desc]
|
47
|
+
define_method("#{name}?") do
|
48
|
+
@value & mask == mask
|
49
|
+
end
|
50
|
+
define_method("#{name}!") do
|
51
|
+
@value |= mask
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# Interpret the bits in the +bit_range+ (starting from zero) as unsigned integer named +name+
|
57
|
+
# (should be a Symbol). The optional parameter +desc+ can be used to provide a textual
|
58
|
+
# representation of the meaning of the value.
|
59
|
+
#
|
60
|
+
# This method also adds accessor methods for the property. For example, if the property is
|
61
|
+
# called +version+, the created getter method is called <tt>#version</tt> and the setter
|
62
|
+
# method is called <tt>#version=</tt>.
|
63
|
+
#
|
64
|
+
# Example usage:
|
65
|
+
#
|
66
|
+
# unsigned 2..5, :version, 'The integer version of the AMT device'
|
67
|
+
def self.unsigned(bit_range, name, desc = name.to_s)
|
68
|
+
mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
|
69
|
+
(@unsigned ||= []) << [name, desc]
|
70
|
+
define_method(name) do
|
71
|
+
(@value & mask) >> bit_range.begin
|
72
|
+
end
|
73
|
+
define_method("#{name}=") do |number|
|
74
|
+
@value |= (number << bit_range.begin) & mask
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Interpret the bits in the +bit_range+ (starting from zero) as unsigned integer value of an
|
79
|
+
# enumeration called +name+ (should be a Symbol).
|
80
|
+
#
|
81
|
+
# The parameter +values+ specifies the mapping from number to meaning (normally a String). The
|
82
|
+
# optional parameter +desc+ can be used to provide a textual representation of the meaning of
|
83
|
+
# the enumeration.
|
84
|
+
#
|
85
|
+
# This method also adds accessor methods for the property. For example, if the property is
|
86
|
+
# called +version+, the created getter method is called <tt>#version</tt> and the setter
|
87
|
+
# method is called <tt>#version=</tt>.
|
88
|
+
#
|
89
|
+
# Example usage:
|
90
|
+
#
|
91
|
+
# enum 0..1, :device_type, {0 => 'Foo', 1 => 'Bar', 2 => 'Baz', 3 => Quux'}
|
92
|
+
def self.enum(bit_range, name, values, desc = name.to_s)
|
93
|
+
mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
|
94
|
+
(@enum ||= []) << [name, values, desc]
|
95
|
+
define_method(name) do
|
96
|
+
values[(@value & mask) >> bit_range.begin]
|
97
|
+
end
|
98
|
+
define_method("#{name}=") do |number|
|
99
|
+
@value |= (number << bit_range.begin) & mask
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return a hash of all defined fields for this class. The hash keys are <tt>:boolean</tt> for
|
104
|
+
# the boolean properties, <tt>:unsigned</tt> for the unsigned integer properties and
|
105
|
+
# <tt>:enum</tt> for the enumeration properties. The hash values are arrays with information
|
106
|
+
# (depending on the type of the field) about the fields.
|
107
|
+
def self.fields
|
108
|
+
{:boolean => @boolean || [], :unsigned => @unsigned || [], :enum => @enum || []}
|
109
|
+
end
|
110
|
+
|
111
|
+
# The integer value which should be interpreted bit-wise.
|
112
|
+
attr_reader :value
|
113
|
+
|
114
|
+
# Create a new object. If +value+ is an integer, it is used directly and interpreted bit-wise.
|
115
|
+
# If +value+ is an array, it is processed in the following way:
|
116
|
+
#
|
117
|
+
# * symbols are interpreted as boolean fields
|
118
|
+
# * two-item arrays where the first item is a symbol and the second an integer are interpreted
|
119
|
+
# as unsigned or enum fields (depending in which category the symbol falls).
|
120
|
+
def initialize(value = 0)
|
121
|
+
if value.kind_of?(Integer)
|
122
|
+
@value = value
|
123
|
+
elsif value.kind_of?(Array)
|
124
|
+
@value = 0
|
125
|
+
value.each do |sym, val|
|
126
|
+
if val.nil?
|
127
|
+
send("#{sym}!")
|
128
|
+
else
|
129
|
+
send("#{sym}=", val)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
else
|
133
|
+
raise ArgumentError, 'invalid argument type specified'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def inspect #:nodoc:
|
138
|
+
bools = self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n, d| n.to_s}
|
139
|
+
unsigns = self.class.fields[:unsigned].collect {|n, d| "#{n}=#{send(n)}"}
|
140
|
+
enum = self.class.fields[:enum].collect {|n, d| "#{n}=#{send(n)}"}
|
141
|
+
"#<#{self.class.name} #{(bools + unsigns + enum).join(', ')}>"
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return an array with textual representations for output purposes of the the fields specified
|
145
|
+
# by +used_fields+.
|
146
|
+
def list(used_fields = [:boolean, :unsigned, :enum])
|
147
|
+
result = []
|
148
|
+
if used_fields.include?(:boolean)
|
149
|
+
result += self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n,d| d}
|
150
|
+
end
|
151
|
+
if used_fields.include?(:unsigned)
|
152
|
+
result += self.class.fields[:unsigned].collect {|n, d| "#{d}=#{send(n)}"}
|
153
|
+
end
|
154
|
+
if used_fields.include?(:enum)
|
155
|
+
result += self.class.fields[:enum].collect {|n, d| "#{d}=#{send(n)}"}
|
156
|
+
end
|
157
|
+
result
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|