Dear Daniele, I'm trying to create a subdriver for 'nutdrv_qx' instead of modifying the Blazer as you suggested, but i honestly don't understand how to integrate usb-serial devices (some of our UPSs have USB but serial protocol Q1). i understand the serial version but not the USB one. i also checked the "Claim" function, but i can't see drivers that uses the VID and PID to match the device (for nutdrv_qx). if you have the name of a usb driver for nutdrv_qx could be really helpful and i will study on top of it, otherwise if you have any docs regarding this please send me the link! I also checked the nutdrv_qx.c and i found "Krauler subdriver", but i'm not sure how it works. thanks in advance, Best Regards, Gabriele Taormina ________________________________ Da: Daniele Pezzini <hyouko at gmail.com> Inviato: giovedì 12 luglio 2018 02:20 A: Gabriele TAORMINA Cc: nut-upsdev at alioth-lists.debian.net; Thierry DESTRUEL; Stefano PONGILUPPI Oggetto: Re: [Nut-upsdev] Adding drivers to NUT?> - I can send you the whole sources for our UPSs, do you need only Headers > and C files or also other files (i suppose Driver list)?If you can't generate a patch yourself (either `diff -u` or `git format-patch`, well probably even `git diff`, will do), send any file you've touched and tell us from what you started.> - Seen that we had some problems with the Blazer driver (the battery voltage > calculation were not correct for our UPSs) we copied it and modified a bit > while changing the name, is this possible or it's a problem for devs?Generally speaking, it's not a problem, as long as copyright and license are respected -- it's more a question of opportunity, then: is it worth creating a new driver if the changes are not big? Since you mention the blazer drivers, if your devices use a Q1-like protocol that is not already supported by the nutdrv_qx driver, if feasible, you should add a subdriver to it (or modify an existing one), rather than creating a new driver. See: https://networkupstools.org/docs/developer-guide.chunked/ar01s04.html#nutdrv_qx-subdrivers> We have no problems to send you protocols of our UPSs.Good to hear. If you send this first, we can decide together what's the best solution. ________________________________ Ce message, ainsi que tous les fichiers joints à ce message, peuvent contenir des informations sensibles et/ ou confidentielles ne devant pas être divulguées. Si vous n'êtes pas le destinataire de ce message (ou que vous recevez ce message par erreur), nous vous remercions de le notifier immédiatement à son expéditeur, et de détruire ce message. Toute copie, divulgation, modification, utilisation ou diffusion, non autorisée, directe ou indirecte, de tout ou partie de ce message, est strictement interdite. This e-mail, and any document attached hereby, may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized, direct or indirect, copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://alioth-lists.debian.net/pipermail/nut-upsdev/attachments/20180718/4ef9eb70/attachment.html>
aehm.. the innards of nutdrv_qx are not exactly well documented (and
vars have somewhat confusing names) -- my fault, sorry.
This is another thing that has been on my todo list for a while...
Briefly, at the moment, in nutdrv_qx, there are actually two kinds of
subdrivers:
- 'protocols', which are communication-type-agnostic (i.e. they do not
fiddle with serial or USB operations, and are not restrained by them),
only map the protocol used by the device to the protocol used by NUT,
and are implemented in their own files using (and exposing only) the
`subdriver_t` format (for more info on this type, see the chapter of
the developer guide I mentioned before, 'nutdrv_qx.h' or the various
'nutdrv_qx_<name-of-the-protocol>.c' files),
- 'USB subdrivers', which only deal with USB I/O operations, and,
conversely, are implemented entirely in 'nutdrv_qx.c'.
With regard to 'protocols', nutdrv_qx works like this:
- 'nutdrv_qx.c''s `subdriver_list` lists the various
(#include'd)
'protocols' the driver supports.
- Once nutdrv_qx has set up the communication with a supported device
in `upsdrv_initups()` (see below, for serial or USB devices), it gives
all (unless otherwise instructed by the user) 'protocols' in
`subdriver_list` a few tries by calling their 'claim()' function
(which usually tries to read some vars from the device to see if it's
actually 'speaking' that protocol): the first one to successfully
claim (i.e. the 'claim()' function returns 1) the device wins.
- From then on, nutdrv_qx uses that 'protocol' when communicating
(e.g. updating the vars, sending instant commands, ...) with the
device: the mapping in the 'qx2nut' table, the
'accepted'/'rejected'
strings, etc.
Now, onto communications (entirely in 'nutdrv_qx.c')...
For serial devices:
- given that, so far, all supported devices shared similar settings
and I/O modus operandi, operations are done directly without much
fanfare...
- setup is done directly in `upsdrv_initups()`,
- ditto for subsequent communications, in `qx_command()`.
For USB devices:
- `qx_usb_id` lists the various VID:PID pairs (with, optionally and
only if needed, the iManufacturer and iProduct strings) of each
supported device, coupled with a function ('fun()' from now on) that
will set `subdriver_command` to point to the function ('command()'
from now on) later used to communicate with the device.
- When nutdrv_qx starts, in `upsdrv_initups()`, it will either pick
the USB subdriver (whose name must be mapped to its relative
'command()' in the `usbsubdriver` list) directly if it was explicitly
provided by the user or, for each available USB device, traverse the
`qx_usb_id` lists, until it finds a match (VID:PID +
iManufacturer/iProduct) and then call its 'fun()' function -- in both
cases, the result is that, if a supported device is found,
`subdriver_command` points to the right 'command()' function.
- Later, every time nutdrv_qx needs to send anything to the device and
to get a reply from it (i.e. in the `qx_command()` function), it will
call the function ('command()') pointed to by `subdriver_command`:
this 'command()' function will receive a null-terminated byte string,
a buffer and its size, and will do all the needed things to a) send
the string to the device and b) get the reply from the device and
store it in the buffer (for example, sending the string verbatim to a
control endpoint and then reading the reply, or mapping the string it
gets to the index of a string descriptor, that, once retrieved, will
hold the reply).
A couple of examples worth a thousand words:
- adding a 'protocol':
https://github.com/networkupstools/nut/commit/dc1e0799277008dcd2c2fad6bc3f59455b242d14
- adding a 'USB subdriver':
https://github.com/networkupstools/nut/commit/3370bbf3ca2d8f95346487938895c494e363186f
Clearer, now?
Dear Daniele,
i understand perfectly, i'd like to explain you why we choosed to clone the
blazer_usb driver:
some of our devices uses Voltronic Q1 protocol and we tried the Krauler
Subdriver (it was the one with the right "commands", Q1, F, etc.), but
the issues were 2:
- first: the Krauler Subdriver expects a different number of bytes in answer
because in debug i see "Short Reply" (if i send Q1 to the UPS it will
answer with 47 Bytes, CR terminated), from what i understand there is something
wrong with the last byte that somewhere is not counted (because if i use a
serial terminal and send Q1 the UPS answer correctly with the number of bytes
required)
- second: the battery voltage low and high (estimated) were not acceptable for
our UPSs because the % level will never reach the 100% and the voltage
estimation was wrong.
- third: we have products with VID and PID: FFFF 0000, this is a problem because
the combination is occuped by Krauler and in this way it will match each time
with the wrong subdriver (krauler instead of our).
now the question i've for you: can we create a clone of nutdrv_qx, but with
the differences shown before? do you have other solutions?
thanks for the support!
Best Regards,
Gabriele Taormina
UPS Strategic Business Unit
Field Application Engineer
Phone: +39 0522/207046
Fax: +39 0522/207005
Address: Via Rodano 1 - Reggio Emilia - 42124 - Italy
Email: gabriele.taormina at legrand.com<mailto:gabriele.taormina at
legrand.com>
<mailto:gabriele.taormina at legrand.com>Website:
www.ups.legrand.com<http://www.ups.legrand.com/>
Website: www.legrand.com<http://www.legrand.com/>
[1506322600142_legrand-vector-logo.png]
________________________________
Da: Daniele Pezzini <hyouko at gmail.com>
Inviato: sabato 21 luglio 2018 02:48:25
A: Gabriele TAORMINA
Cc: nut-upsdev at alioth-lists.debian.net; Thierry DESTRUEL; Stefano PONGILUPPI
Oggetto: Re: [Nut-upsdev] Adding drivers to NUT?
aehm.. the innards of nutdrv_qx are not exactly well documented (and
vars have somewhat confusing names) -- my fault, sorry.
This is another thing that has been on my todo list for a while...
Briefly, at the moment, in nutdrv_qx, there are actually two kinds of
subdrivers:
- 'protocols', which are communication-type-agnostic (i.e. they do not
fiddle with serial or USB operations, and are not restrained by them),
only map the protocol used by the device to the protocol used by NUT,
and are implemented in their own files using (and exposing only) the
`subdriver_t` format (for more info on this type, see the chapter of
the developer guide I mentioned before, 'nutdrv_qx.h' or the various
'nutdrv_qx_<name-of-the-protocol>.c' files),
- 'USB subdrivers', which only deal with USB I/O operations, and,
conversely, are implemented entirely in 'nutdrv_qx.c'.
With regard to 'protocols', nutdrv_qx works like this:
- 'nutdrv_qx.c''s `subdriver_list` lists the various
(#include'd)
'protocols' the driver supports.
- Once nutdrv_qx has set up the communication with a supported device
in `upsdrv_initups()` (see below, for serial or USB devices), it gives
all (unless otherwise instructed by the user) 'protocols' in
`subdriver_list` a few tries by calling their 'claim()' function
(which usually tries to read some vars from the device to see if it's
actually 'speaking' that protocol): the first one to successfully
claim (i.e. the 'claim()' function returns 1) the device wins.
- From then on, nutdrv_qx uses that 'protocol' when communicating
(e.g. updating the vars, sending instant commands, ...) with the
device: the mapping in the 'qx2nut' table, the
'accepted'/'rejected'
strings, etc.
Now, onto communications (entirely in 'nutdrv_qx.c')...
For serial devices:
- given that, so far, all supported devices shared similar settings
and I/O modus operandi, operations are done directly without much
fanfare...
- setup is done directly in `upsdrv_initups()`,
- ditto for subsequent communications, in `qx_command()`.
For USB devices:
- `qx_usb_id` lists the various VID:PID pairs (with, optionally and
only if needed, the iManufacturer and iProduct strings) of each
supported device, coupled with a function ('fun()' from now on) that
will set `subdriver_command` to point to the function ('command()'
from now on) later used to communicate with the device.
- When nutdrv_qx starts, in `upsdrv_initups()`, it will either pick
the USB subdriver (whose name must be mapped to its relative
'command()' in the `usbsubdriver` list) directly if it was explicitly
provided by the user or, for each available USB device, traverse the
`qx_usb_id` lists, until it finds a match (VID:PID +
iManufacturer/iProduct) and then call its 'fun()' function -- in both
cases, the result is that, if a supported device is found,
`subdriver_command` points to the right 'command()' function.
- Later, every time nutdrv_qx needs to send anything to the device and
to get a reply from it (i.e. in the `qx_command()` function), it will
call the function ('command()') pointed to by `subdriver_command`:
this 'command()' function will receive a null-terminated byte string,
a buffer and its size, and will do all the needed things to a) send
the string to the device and b) get the reply from the device and
store it in the buffer (for example, sending the string verbatim to a
control endpoint and then reading the reply, or mapping the string it
gets to the index of a string descriptor, that, once retrieved, will
hold the reply).
A couple of examples worth a thousand words:
- adding a 'protocol':
https://github.com/networkupstools/nut/commit/dc1e0799277008dcd2c2fad6bc3f59455b242d14
- adding a 'USB subdriver':
https://github.com/networkupstools/nut/commit/3370bbf3ca2d8f95346487938895c494e363186f
Clearer, now?
________________________________
Ce message, ainsi que tous les fichiers joints ? ce message, peuvent contenir
des informations sensibles et/ ou confidentielles ne devant pas ?tre divulgu?es.
Si vous n'?tes pas le destinataire de ce message (ou que vous recevez ce
message par erreur), nous vous remercions de le notifier imm?diatement ? son
exp?diteur, et de d?truire ce message. Toute copie, divulgation, modification,
utilisation ou diffusion, non autoris?e, directe ou indirecte, de tout ou partie
de ce message, est strictement interdite.
This e-mail, and any document attached hereby, may contain confidential and/or
privileged information. If you are not the intended recipient (or have received
this e-mail in error) please notify the sender immediately and destroy this
e-mail. Any unauthorized, direct or indirect, copying, disclosure, distribution
or other use of the material or parts thereof is strictly forbidden.
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://alioth-lists.debian.net/pipermail/nut-upsdev/attachments/20180724/3b99d11f/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Outlook-1506322600.png
Type: image/png
Size: 4655 bytes
Desc: Outlook-1506322600.png
URL:
<http://alioth-lists.debian.net/pipermail/nut-upsdev/attachments/20180724/3b99d11f/attachment-0001.png>