-
-
Notifications
You must be signed in to change notification settings - Fork 350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with NUTDRV_QX, subdriver armac (add EOL support) #2003
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1838,14 +1838,20 @@ static int armac_command(const char *cmd, char *buf, size_t buflen) | |
tmpbuf[0], tmpbuf[1], tmpbuf[2], tmpbuf[3], tmpbuf[4], tmpbuf[5], | ||
tmpbuf[1], tmpbuf[2], tmpbuf[3], tmpbuf[4], tmpbuf[5]); | ||
|
||
/* This includes status/length byte on R/3000I/PF1 */ | ||
bytes_available = (unsigned char)tmpbuf[0] & 0x0f; | ||
if (bytes_available == 0) { | ||
/* End of transfer */ | ||
break; | ||
} | ||
|
||
memcpy(buf + bufpos, tmpbuf + 1, bytes_available); | ||
bufpos += bytes_available; | ||
memcpy(buf + bufpos, tmpbuf + 1, bytes_available - 1); | ||
bufpos += bytes_available - 1; | ||
|
||
if (tmpbuf[bytes_available - 1] == 0x0d) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be safe in all cases... (although it uses the bytes_available as well and it's suspicious that it worked without -1 previously). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At least, it is unsigned and non-zero (per previous checks), so array-wise the expression is safe :) |
||
/* End of line is an end of the message as well */ | ||
break; | ||
} | ||
|
||
if (bytes_available <= 2) { | ||
/* Slow down, let the UPS buffer more bytes */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like a simple mistake in dropping
-1
. My UPS rather wouldn't work with it. Maybe it needs some kind of a detection on how this byte is coded. I need traces from both UPSes to make certain it will cover both cases.Maaaybe the original issue were I did this driver has one...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be #1238 and #1239 I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise, initially copying all of
bytes_available
in the original loop seemed reasonable. Say the usb method returned one new byte, here now you'd copy1 - 1 == 0
bytes (and check if that one is end of line)...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there seem to be only a trace where UPS send 1 byte at a time during each interrupt transfer:
Here bytes available (low nibble: tmpbuf[0] & 0x0f) seems to be equal to 1 and convey a 1 byte. Interrupt transmits 6 bytes at a time, but the rest is filled with literal ASCII 0. (would be cool if they used ZERO 0x00).
Current trace:
The first nibble oscillates between
a
and8
- previouslyc
and8
.But TBH, that seems like an easy fix. I'd assume this
6
means this UPS has available 6 bytes in a buffer. This interrupt transfer transferred 5... it can't transfer more. It's just FASTER than the previous model.Instead of
-1
one could:Or even use the 'ret' from usb interrupt in case it can transfer more later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My current take is this one:
It compiles, but could use some testing. ;-) Hopefully it will handle both cases without additional
-1
magic.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, looking at the data dumps in #1978 (comment) :
So for a line where we have lower nibble (first byte
& 0x0f
) equal to6
andret==6
, we have 5 protocol content bytes. However in the last practical line, with the 0x0d, the nibble is3
and there are 2 content bytes (and the UPS stops sending more, hence the timeout).I believe, what the driver did originally, with your UPS where its nibble was
1
it copied one byte into the buffer. Where the nibble was6
it probably copied 6 bytes (starting fromtmpbuf+1
so overflowing thetmpbuf
defined with size 6 exactly... wondering why compilers or run-times did not complain/segfault - not a write so don't care?) and probably adding garbage into that extra byte of the resulting string for each loop :\There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I've dropped ret - 1 because 6 is hardcoded above. (Original driver does reads always by 6 bytes). But that's equivalent - if ret != 6 we bail out anyway.
In general we can introduce a constant:
const int READ_SIZE = 6;
Use it in usb_interrupt_read, in following if and later instead of
ret
- it will be cleaner and I can prepare a patch like that.Architecture-wise, I believe the UPS works like this:
([controller] --uart or rs232-- [usb bridge with buffer]) --usb-- [PC]
And this USB interface is a really poor USB Serial implementation. ;)
So the
bytes_available
is not a length of a whole serial buffer, just the amount that currently is stored within the usb bridge. MAYBE. As far as we can tell. It's important to differentiate a TRUE data from a fill (0, 0x30), when there's less data then the read size certainly. Would not be necessary if the fill was 0x00. I think deducting 5 is worthless, but we could store info likemore_available = true
if it's larger thanREAD_SIZE - 1
.Unsure what to do with this information though. If we find
\x0d
butmore_available == true
that's probably an error and we could print a message - not much more though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Watchout for the \r that shifts the 0 in the output in those lines. But yes, nibble is 3 and there are pretty much 2 bytes sent. I forgot about it today - and it suggest I should scan for \d and not just check the last byte.
Driver when the nibble was 6 could be reading 1 byte over tmpbuf. C compilers and run-times are quirky. :S In Rust that would certainly be a runtime Panic, maybe compilation error. tmpbuf is on the stack, so there's a big chance it was reading 1 byte more from the stack just.
Certainly adding a garbage - that changed the meaning of this nibble in a way not observed in other UPSes.
I'll take a look at this final byte too, maybe it needs special handling to find \r correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will be more productive for you to cherry-pick the changes I've proposed so far and start another PR from your fork to override this one, to avoid me posting your patches from discussion into git :) WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, certainly. The problem is - testing. I can probably get this changes tested on the new UPS. Trouble is, to check on mine/other ones. When my sister is watering the plants I'll ask her to power it on; maaaybe I could do it remotely. (;