[Nut-upsdev] Re: Serial Ports (Was Re: Common Power Management : NUT and HAL (stage 1))

Arnaud Quette aquette.dev at gmail.com
Thu Aug 31 11:47:52 UTC 2006


2006/8/7, David Zeuthen <david at fubar.dk>:
> On Thu, 2006-08-03 at 21:28 +0200, Arnaud Quette wrote:
> > > > > * serial and snmp drivers are not yet managed,
> >
> > you once proposed me to sketch that one Dave ;-)
>
> Indeed I did! So here goes:
>
> So my proposal isn't really confined to serial ports but any port where
> we cannot automatically detect a device.

I wasn't waiting for less from you ;-)

> Here's a few statements
>
>  a) we need user input on configuring the port - this means the user
>     needs to choose what device sits on the port, be it a UPS, a
>     GPS receiver, modem, smart card reader, input device and so on.
>     After the user chooses the device type, we should check that the
>     device he chose is actually on the port before it is configured.

NUT provide an helper which is the (parsable) compat list, listing
mfr, model (+extra info) and the according driver:
http://svn.debian.org/wsvn/nut/trunk/data/driver.list?op=file&rev=0&sc=0

that allows GUIs to present choice in a friendly way, ie:
http://www.alo.cz/knutsetting/images/modules_add_en.png

>  b) the stock install of HAL should leave the ports unconfigured
>
>  c) it needs to be easy for a program to configure the port - OS
>     installers and desktop programs come to mind.
>
>  d) once configured we should remember the configuration on hal restarts
>
>  e) the configuration is bound to the system scope, e.g. it doesn't
>     change when the user changes
>
>  f) the configuration is bound to the physical machine, e.g. if you
>     move the system disk to another system the port should be
>     unconfigured when you boot into the new system
>     (use-case: boot from USB)
>
>  g) it must be easy for external packages (like nut, gpsd etc.) to tell
>     HAL that it wants to participate in configuring a port.

more details needed...

>  h) we should provide a textual hal utility for configuring a port
>
> So the serial port on my desktop system looks like this
>
> udi = '/org/freedesktop/Hal/devices/pnp_PNP0501_serial_platform_0'
>   info.udi = '/org/freedesktop/Hal/devices/pnp_PNP0501_serial_platform_0'  (string)
>   linux.device_file = '/dev/ttyS0'  (string)
>   linux.subsystem = 'tty'  (string)
>   linux.hotplug_type = 2  (0x2)  (int)
>   info.product = '16550A-compatible COM port'  (string)
>   serial.type = 'platform'  (string)
>   serial.port = 0  (0x0)  (int)
>   serial.device = '/dev/ttyS0'  (string)
>   serial.physical_device = '/org/freedesktop/Hal/devices/pnp_PNP0501'  (string)
>   info.capabilities = {'serial'} (string list)
>   info.category = 'serial'  (string)
>   info.parent = '/org/freedesktop/Hal/devices/pnp_PNP0501'  (string)
>   linux.sysfs_path = '/sys/class/tty/ttyS0'  (string)
>
> The proposal involves
>
>  1. all device objects representing legacy ports are tagged with the
>     capability "legacy_port". This is easy to do.
>
>  2. we introduce new properties
>
>      legacy_port.type             (string)
>
>     that indicates the type of the port, e.g. "serial". Later on we can
>     add e.g. "parallel" or other types.
>
>      legacy_port.is_configured    (bool)
>
>     this property is TRUE if, and only if, the port is configured.
>
>      legacy_port.configured_type  (string)
>
>     if is_configured==TRUE, this is the ''type'' of device the device
>     is configured as. The ''type'' is defined below.
>
>      legacy_port.probers.type         (strlist)
>      legacy_port.probers.capabilities (strlist)
>      legacy_port.probers.programs     (strlist)
>
>     These three properties are filled by either in-tree HAL programs or
>     external packages like e.g. NUT that wants to participate in
>     configuring legacy ports. It may look like this
>
>      legacy_port.probers.type         = {"nut-serial-ups",        "gpsd-serial-gps",   "hal-serial-modem", ...}
>      legacy_port.probers.capabilities = {"battery.ups",           "gps",               "modem", ...}
>      legacy_port.probers.programs     = {"nut-hal-serial-prober", "gpsd-serial-probe", "hal-serial-modem-probe", ...}
>
>     where .type contains a opaque type specific to the provider,
>     .capabilities contains HAL capabilities that will be provided if
>     bound, and .programs is a program to actually test to see if there
>     is a device.

see my comment below about .program

>     This is easy to provide for e.g. NUT, it simply includes a HAL FDI
>     file that looks somewhat like this
>
>                 <deviceinfo version="0.2">
>                   <device>
>                     <match key="legacy_port.type" string="serial">
>                       <append key="legacy_port.probers.type"         type="strlist">nut-serial-ups</append>
>                       <append key="legacy_port.probers.capabilities" type="strlist">battery.ups</append>
>                       <append key="legacy_port.probers.programs"     type="strlist">nut-hal-serial-prober</append>
>                     </match>
>                   </device>
>                 </deviceinfo>

there is a big problem here:
NUT can't provide a generic serial prober since there are far too many
protocols, and issuing some wrong protocol commands might have bad
effect on wrong UPS.

so the only thing we (NUT) can do is to provide a list in which the
user will pick his mfr/model, and then launch the right driver in
probe mode to see if the device is there.

Note that this probe mode is not yet implemented, though it can be
easily done. It's simply a "-p" flag that cause the driver to exit
after the driver discovery function (upsdrv_initinfo()), printing out
mfr/model info or some magic if nothing was detected...

>  3. With the legacy_port.* properties we can now provide a sane UI
>     (both API and UI-wise) to provide probing for serial devices. Said
>     configuration programs would look at legacy_port.probers.
>     capabilities which contains well-defined HAL capabilities that can
>     be translated into the users language. So in addition to the
>     legacy_port capability we'd export an interface with methods called
>
>      org.freedesktop.Hal.Device.LegacyPort
>
>     with methods
>
>      UnconfigurePort()
>
>     to simply unconfigure a port and,
>
>      ConfigurePort (IN int proberNumber)
>        throws AlreadConfiguredException,
>               NoSuchProberException,
>               ProberDidNotFindDeviceException
>
>     where the latter method, ConfigurePort, will try to run the
>     requested prober. If that fails (e.g. return code is != 0) then
>     this exception is thrown. If it succeeds, then the properties
>     legacy_port.is_configured and legacy_port.configured_type
>     is set accordingly.
>
>     It should be trivial to write a textual based program that does
>     exactly this and we will do this and include it in tools/ along
>     with other smallish tools such as lshal. Similary, programs
>     such as gnome-volume-manager (which really should be gnome-hardware-
>     manager) would be able to provide the UI for this etc. etc.
>
>  4. To preserve the value of the properties
>
>      legacy_port.is_configured,
>      legacy_port.configured_type
>
>     across HAL restarts, the ConfigurePort() method simply saves
>     the values somewhere in /var/run/hald/blah and we have a callout
>     on the device object pick them up. The file name chosen to save
>     it under will include system.product and system.product from the
>     /o/fd/Hal/d/computer object to satisfy requirement f) above.
>
> So now we have provided infrastructure for the user to configure the
> legacy port. To actually do something with this, software such as NUT
> simply includes an FDI file like this
>
>         <deviceinfo version="0.2">
>           <device>
>             <match key="legacy_port.configured_type" contains="nut-serial-ups">
>               <append key="info.addons" type="strlist">nut-addon-for-serial-ups</append>
>             </match>
>           </device>
>         </deviceinfo>
>
> and since this is on the device object for the UDI
>
>  /org/freedesktop/Hal/devices/pnp_PNP0501_serial_platform_0
>
> that I listed above you are guaranteed to have the device file in the
> property serial.device and you can go from there.
>
> There's a few gotchas in the implementation, but this is pretty much how
> I envision we should do this. I'm pretty sure this would work and if
> there is consensus I'm happy to do the work for this infrastructure as
> well for the serial modem stuff (I don't have a serial UPS).

you will have an MGE unit soon, with both USB and serial connection ;-)

> Of course, if someone wants to hack on this, I'm happy to review patches
> also :-)
>
> Thoughts?

one more important thought:
nut drivers generally need some more config param. Ie some generic
drivers (like genericups, a generic dry contact UPS driver) need a
mandatory upstype to know which serial pin match which UPS signal (ie
DCD = low battery).

we have 2 choices here:

1) rely upon the nut config files to define detailed options.

- the below things are based on the new NUT config format and tools,
not yet available in the trunk, but from the JD-NewConf branch and
scheduled for nut 2.2
- the config is in the form:
mode = "pm"
ups.myups (
        driver.name = genericups
        driver.parameter.port = /dev/ttyS0
        driver.parameter.upstype = 1
)

- it only requires the ups section name ("myups" here) on the HAL
side, then the nut driver will take care of finding its info to run.
Ie
- the HAL config is in the form:
       <deviceinfo version="0.2">
         <device>
           <match key="legacy_port.configured_type" contains="nut-serial-ups">
             <append key="info.addons"
type="strlist">hald-addon-genericups</append>
             <append key="info.addons.ups-name" type="int">myups</append>
           </match>
         </device>
       </deviceinfo>

- the addon has to be called using "addon-name -a ups-name"
- the NUT compat list (drivers.list) include the mandatory parameters
for the exact model, if any or none otherwise.
ie the right upstype for genericups:
"mfr"	"model"		""	"genericups upstype=1"

- NUT provides libupsconfig to configure things easilly (ie
configuring in pm-Power Management mode for a serial unit is few lines
of code):
> new_config();
> set_mode("pm");
> add_ups("myups", "genericups", "/dev/ttyS0");
> set_driver_parameter("upstype", "1", string_type);
> save_config(destination, comments_template, 1, error_handler);

-everything has been prepared by Jonathan Dion, during his internship
at MGE (ending today), to deal with such a case,
- this leaves all the UPS specifics outside of HAL, and is IMO the
best approach, though it has to be generic (ie gpsd must also have the
same approach?). This is also the simplest approach for the nut
driver, since the same config code is used.


2) Store things in the HAL file, ie:

- the hal config is in the form:
       <deviceinfo version="0.2">
         <device>
           <match key="legacy_port.configured_type" contains="nut-serial-ups">
             <append key="info.addons"
type="strlist">hald-addon-genericups</append>
             <append key="info.addons.upstype" type="int">1</append>
           </match>
         </device>
       </deviceinfo>

- that implies g-p-m (or other apps) will manages that format
- it has the advantage to centralise config things, but the
disadvantage to need some specific code in the nut drivers to read
this, though is simply some hal_get queries.

Final notes:
- when I've not made comment on some points, things suits me fine,
- NUT serial addons for hald are not scheduled for nut 2.2 (I'll
detail this in my answer to the CPM thread), so there is no hurry on
my side. I'll first limit to USB drivers.

ping...

Arnaud
-- 
Linux / Unix Expert - MGE UPS SYSTEMS - R&D Dpt
Network UPS Tools (NUT) Project Leader - http://www.networkupstools.org/
Debian Developer - http://people.debian.org/~aquette/
OpenSource Developer - http://arnaud.quette.free.fr/



More information about the Nut-upsdev mailing list