Re: uhidpp(4): add support for Bolt receivers and Unified Battery feature

2022-11-26 Thread David Higgs
On Sat, Nov 26, 2022 at 1:47 AM Anton Lindqvist  wrote:

> Hi,
> This diff adds supports for the following to uhidpp:
>
> 1. Bolt receivers, they use a different set of registers for querying
>paired devices.
>
> 2. The Unified Battery feature, this is a more competent feature
>function used to report battery status compared to the Battery
>feature which is already supported by uhidpp.
>
> Makes battery sensors appear for my Logitech Lift mouse and Paul de
> Weerd's MX Anywhere 3 mouse.
>
> If you have a Logitech HID++ device currently lacking sensors under
> sysctl hw.sensors, please give this diff a try. Send me your dmesg and
> output of sysctl hw.sensors after moving the mouse to ensure a connect
> interrupt has fired off. Note that the diff must be applied on top of
> revision 1.37 of sys/dev/usb/uhidpp.c.
>
> Comments? OK?
>


> 
> @@ -193,17 +202,20 @@ struct uhidpp_device {
> uint8_t d_features;
>  #define UHIDPP_DEVICE_FEATURE_ROOT 0x01
>  #define UHIDPP_DEVICE_FEATURE_BATTERY  0x02
> +#define UHIDPP_DEVICE_FEATURE_UNIFIIED_BATTERY 0x04
>
> 
>

Do you actually mean "unifiied" with an extra "i" here?

--david


Re: cron(8): add '@' interval time specifier

2021-07-15 Thread David Higgs
On Thu, Jul 15, 2021 at 11:20 AM Leo Unglaub  wrote:

> Hey,
> this is a very clean solution to a very common problem that i have. A
> lot of tasks that i run from cron have very different completion times.
> Right now i use the -s [1] option in crontab to make sure only one task
> is running at once and so that they don't overlap if they take longer to
> complete than the interval i schedule them. But the problem with the -s
> workflow is that the interval can get messed up if the interval is
> smaller than the execution period. This will basically "skip" a run.
>
> With your patch this can be avioded in a very clean way. I have your
> patch a try and for my local testing usecase it worked as expected. This
> would clean up a lot of things in my personal workflow. Thank you very
> mich for the patch Job, much appreciated!
>
> Thanks and greetings
> Leo
>
> [1] https://man.openbsd.org/crontab.5#s
>
> On 10/07/2021 16:07, Job Snijders wrote:
> > The below patch adds a new kind of time specifier: an interval (in
> > minutes). When used, cron(8) will schedule the next instance of a job
> > after the previous job has completed and a full interval has passed.
> >
> > A crontab(5) configured as following:
> >
> >  $ crontab -l
> >  @3 sleep 100
> >
> > Will result in this schedule:
> >
> >  Jul 10 13:38:17 vurt cron[96937]: (CRON) STARTUP (V5.0)
> >  Jul 10 13:42:01 vurt cron[79385]: (job) CMD (sleep 100)
> >  Jul 10 13:47:01 vurt cron[3165]: (job) CMD (sleep 100)
> >  Jul 10 13:52:01 vurt cron[40539]: (job) CMD (sleep 100)
> >  Jul 10 13:57:01 vurt cron[84504]: (job) CMD (sleep 100)
> >
> > A use case could be running rpki-client more frequently than once an
> > hour:
> >
> >  @15 -n rpki-client && bgpctl reload
> >
> > The above is equivalent to:
> >
> >  * * * * * -sn sleep 900 && rpki-client && bgpctl reload
> >
> > I borrowed the idea from FreeBSD's cron [1]. A difference between the
> > below changeset and the freebsd implementation is that they specify the
> > interval in seconds, while the below specifies in minutes. I was able
> > to leverage the 'singleton' infrastructure. And removed a comment that
> > reads like a TODO nobody is going to do.
> >
> > Thoughts?
>

Can't this type of problem also be solved with a shell script wrapper?

An infinite loop that does work and then sleeps?
Or perhaps a script that upon work completion, schedules itself in the
future with at(1)?
These could be kicked off initially with a @reboot crontab entry.

Or maybe I'm missing something that cron adds to the equation, in which
case, apologies.

--david


Re: radeondrm(4) unaligned access fix

2020-10-27 Thread David Higgs
On Mon, Oct 26, 2020 at 3:18 PM Mark Kettenis 
wrote:

> > Date: Sun, 25 Oct 2020 10:42:38 +0100 (CET)
> > From: Mark Kettenis 
> >
> > While making radeondrm(4) work on powerpc64 I'm running into an
> > interesting unaligned access issue.
> >
> > Modern POWER CPUs generally support unaligned access.  Normal load and
> > store unstructions work fine with addresses that aren't naturally
> > aligned when operating on cached memory.  As a result, clang will
> > optimize code by replacing two 32-bit store instructions with a single
> > 64-bit store instruction even if there is only 32-bit alignment.
> >
> > However, this doesn't work for memory that is mapped uncachable.  And
> > there is some code in radeondrm(4) (and also in amdgpu(4)) that
> > generates alignment exceptions because it is writing to bits of video
> > memory that are mapped through the graphics aperture.
> >
> > There are two ways to fix this.  The compiler won't apply this
> > optimization if memory is accessed through pointers that are marked
> > volatile.  Hence the fix below.  In my opinion that is the right fix
> > as rdev->uvd.cpu_addr is a volatile pointer and that aspect shouldn't
> > be dropped.  The downside of this approach is that we may need to
> > maintain some additional local fixes.
> >
> > The alternative is to emulate the access in the kernel.  I fear that
> > is what Linux does, which is why they don't notice this issue.  As
> > such, this issue may crop up in more places and the emulation would
> > catch them all.  But I'm a bit reluctant to add this emulation since
> > it may hide bugs in other parts of our kernel.
> >
> > Thoughts?  ok?
>
> There is more code in radeondrm(4) and amdgpu(4) that is affected by
> this issues and some of it isn't easy to "volatilize".
>
> There is an llvm option to enforce strict alignment, but it isn't
> exposed as a proper option by clang.  I'm still investigating the use
> of that option, but meanwhile I think I'll commit the attached diff
> such that the kernel side of things works and I can look at what needs
> to happen on the userland side.
>

Disclaimer: I'm not an expert in this area.

Seems odd that this problem doesn't affect loads too...

Would it be difficult to also validate that the destination address is
mapped uncached, so that normal userland alignment bugs will still get
caught?

--david


Re: shrinking and growing reallocs: a theoretical? bad case for performance

2020-08-31 Thread David Higgs
On Mon, Aug 31, 2020 at 2:41 AM Otto Moerbeek  wrote:

> Hi,
>
> A question from Theo made me think about realloc and come up with a
> particular bad case for performance. I do not know if it happens in
> practice, but it was easy to create a test program to hit the case.
>
> We're talking allocation >= a page here. Smaller allocation follow
> different rules.
>
> If an allocation is grown by realloc, I first tries to extend the
> allocation by mapping pages next to the existing allocation. Since
> the location of pages is randomized, chanches are high that next to an
> allocation there are unmapped pages so the grow will work out.
>
> If realloc needs to shrink the allocation it puts the high pages no
> longer needed in the malloc cache. There they can be re-used by other
> allocations. But if that happens, next a grow of first allocation will
> fail: the pages are already mapped. So realloc needs to do a new
> allocation followed by a copy and a cleanup of the original.
>
> So this strategy of a shrinking realloc to of put unneeded pages into
> the cache can work against us, plus it has the consequence that use of
> realloc leads to allocations close to each other: no free guard pages.
>

If I am interpreting this correctly, realloc could be used to groom/shape
the heap such that future allocations are less random and more predictable?

--david


Re: symmetric toeplitz hashing

2020-06-13 Thread David Higgs
On Fri, Jun 12, 2020 at 9:41 AM Theo Buehler  wrote:

> I finally found the time to think about the mathematics of this some
> more and I'm now convinced that it's a sound construction. I hope that
> one or the other observation below will be useful for you.
>
> The hash as it is now can be proved to produce values in the full range
> of uint16_t, so that's good.
>
> As we discussed already, you can simplify the construction further.
>

[snip]


> Next, I don't particularly like this magic STOEPLITZ_KEYSEED number, but
> I guess we can live with it.
>
> Another option would be to generate the key seed randomly. You will get
> a "good" hash that spreads out over all 16 bit values if and only if the
> random value has an odd number of binary digits.
>
> I haven't thought hard about this, but I don't immediately see a better
> way of generating such numbers than:
>
> int
> stoeplitz_good_seed(uint16_t seed)
> {
> int ones = 0;
>
> while (seed > 0) {
> ones += seed % 2;
> seed /= 2;
> }
>
> return ones % 2;
> }
>
> uint16_t
> stoeplitz_seed_init(void)
> {
> uint16_tseed;
>
> do {
> seed = arc4random() & UINT16_MAX;
> } while (!stoeplitz_good_seed(seed));
>
> return seed;
> }
>
> This will loop as long as it needs to get a good toeplitz key seed.
> Each time there is a 50% chance that it will find one, so this will
> need to loop n times with probability 1 / 2**n. This is basically the
> same situation as for arc4random_uniform() with an upper bound that is
> not a power of two.
>

I neither read nor understand the math but assuming you've described it
correctly, you can do this more simply by realizing that a random bad seed
can be made into a good seed by toggling one (random) bit.  You also
replace stoeplitz_good_seed() with __builtin_parity() and perhaps leverage
some intrinsics?

uint16_t
stoeplitz_seed_init(void) {
uint16_t seed;
seed = arc4random() & UINT16_MAX;
if (!stoeplitz_good_seed(seed))
seed ^= 1 << (arc4random() % 16);
}

--david


Re: bgpd, Adj-RIB-Out support

2018-10-31 Thread David Higgs
On Wed, Oct 31, 2018 at 6:58 PM Sebastian Benoit  wrote:



On a phone, saw some typos and such, sorry no diff.

[benoit@border2:~]$ cat before
> RDE memory statistics
> 715727 IPv4 unicast network entries using 27.3M of memory
>  58953 IPv6 unicast network entries using 3.1M of memory
>1549171 rib entries using 94.6M of memory
>2897130 prefix entries using 265M of memory
> 562423 BGP path attribute entries using 60.1M of memory
> 149579 BGP AS-PATH attribute entries using 6.1M of memory,
>and holding 562423 references
>  37007 BGP attributes entries using 1.4M of memory
>and holding 880668 references


Inconsistent comma usage above


>  37006 BGP attributes using 912K of memory
>  61964 as-set elements in 58064 tables using 950K of memory
> 103150 prefix-set elments using 4.3M of memory


elments => elements

RIB using 459M of memory
> Sets using 5.2M of memory
>
> RDE hash statistics
> path hash: size 131072, 562423 entires
> min 0 max 20 avg/std-dev = 4.291/2.364
> aspath hash: size 131072, 149579 entires
> min 0 max 8 avg/std-dev = 1.141/0.835
> attr hash: size 16384, 37007 entires
> min 0 max 10 avg/std-dev = 2.259/1.378
>

entires => entries

—david


Re: bsd.rd failure in VirtualBox

2018-09-17 Thread David Higgs
On Sun, Sep 16, 2018 at 1:15 PM, Johan Huldtgren
 wrote:
> On 2018/09/16 10:52, David Higgs wrote:
>> On Sun, Sep 16, 2018 at 10:17 AM, David Higgs  wrote:
>>> On Sat, Sep 15, 2018 at 10:05 PM, Philip Guenther  
>>> wrote:
>>>> On Sat, Sep 15, 2018 at 11:59 AM David Higgs  wrote:
>>>>>
>>>>> I often use VirtualBox (version 5.2.18 on OS X) to familiarize myself
>>>>> with new features in snapshots, before upgrading my physical hardware.
>>>>>
>>>>> This afternoon, I tried updating bsd.rd (amd64, 6.4-beta RAMDISK_CD
>>>>> #281) and wasn't able to successfully boot it.  I had to rely on the
>>>>> video capture ability of VirtualBox to even notice there was a panic
>>>>> (typed out below) before it rebooted to the "BIOS" splash screen.
>>>>
>>>> ...
>>>>>
>>>>> Also attached is the dmesg from a prior working snapshot.  I haven't
>>>>> tried updating since this prior snapshot, so I don't have further
>>>>> insight into when the issue first appeared.
>>>>
>>>>
>>>> Thank you for the complete and clear report!
>>>>
>>>> I have a diff in the amd64 snapshots to use the CPU's PCID support in many
>>>> cases and this VirtualBox setup found a bug in it.  I've generated a new
>>>> diff that should fix this, so a future snap should fix this, though when
>>>> that'll happend depends on the snap builder's schedule.
>>>>
>>>
>>> Not sure if the fix made it into RAMDISK_CD #282, but this panic is
>>> slightly different.  I haven't tried reproducing to see if the panic
>>> message differs between boots.
>>>
>>> 
>>> root on rd0a swap on rd0b dump on rd0b
>>> uvm_fault(0xff011f73ac60, 0x208, 0, 1) -> e
>>> fatal page fault in supervisor mode
>>> trap type 6 code 0 rip 8135510b cs 8 rflags 10246 cr2 208 cpl
>>> 0 rsp 800022026c90
>>> gsbase 0x81870ff0 kgsbase 0x0
>>> panic: trap type 6, code=0, pc=8135510b
>>> syncing disk... done
>>>
>>> dump to dev 17,1 not possible
>>> rebooting...
>>> 
>>>
>>> Hope this helps.
>>>
>>
>> FWIW, the vbox capture feature is pretty buggy - it doesn't create the
>> file when it says it is recording, and it frequently crashes.  It is
>> possible the panic above is from #281 instead, because I deleted the
>> video before I realizing this.
>>
>> Below is definitely from #282.
>>
>> 
>> Welcome to the OpenBSD/amd64 6.4 installation program.
>> fatal protection fault in supervisor mode
>> trap type 4 code 0 rip 810f4244 cs 8 rflags 10286 cr2 6c1fed
>> cpl a rsp 800022098800
>> gsbase 0x81870ff0 kgsbase 0x0
>> panic: trap type 4, code 0, pc=0x 810f4244
>> syncing disks... done
>>
>> dump to dev 17,1 not possible
>> rebooting...
>> 
>>
>> Hope this is actually useful and not another stupid VirtualBox bug.
>
> I see this an almost identical panic on real hardware too, the only difference
> being the string after 'rsp'
>
> Welcome to the OpenBSD/amd64 6.4 installation program.
> fatal protection fault in supervisor mode
> trap type 4 code 0 rip 810f4244 cs 8 rflags 10286 cr2 6c1fed cpl a 
> rsp 8000220ba9e0
> gsbase 0x81870ff0 kgsbase 0x0
> panic: trap type 4, code 0, pc=810f4244
> syncing disks... done
>
> dump to dev 17,1 not possible
> rebooting...
>
> Below is first the working dmesg snapshot, and then one from booting bsd.rd, 
> note
> the ACPI error about not being able to load tables, that's not there on the 
> working
> snap. That might be the culprit at least in my case?
>

FYI - successfully booted with RAMDISK_CD #283 and installed a
successfully-booting GENERIC #284 within VirtualBox.

Thanks again.

--david



Re: bsd.rd failure in VirtualBox

2018-09-16 Thread David Higgs
On Sat, Sep 15, 2018 at 10:05 PM, Philip Guenther  wrote:
> On Sat, Sep 15, 2018 at 11:59 AM David Higgs  wrote:
>>
>> I often use VirtualBox (version 5.2.18 on OS X) to familiarize myself
>> with new features in snapshots, before upgrading my physical hardware.
>>
>> This afternoon, I tried updating bsd.rd (amd64, 6.4-beta RAMDISK_CD
>> #281) and wasn't able to successfully boot it.  I had to rely on the
>> video capture ability of VirtualBox to even notice there was a panic
>> (typed out below) before it rebooted to the "BIOS" splash screen.
>
> ...
>>
>> Also attached is the dmesg from a prior working snapshot.  I haven't
>> tried updating since this prior snapshot, so I don't have further
>> insight into when the issue first appeared.
>
>
> Thank you for the complete and clear report!
>
> I have a diff in the amd64 snapshots to use the CPU's PCID support in many
> cases and this VirtualBox setup found a bug in it.  I've generated a new
> diff that should fix this, so a future snap should fix this, though when
> that'll happend depends on the snap builder's schedule.
>

Not sure if the fix made it into RAMDISK_CD #282, but this panic is
slightly different.  I haven't tried reproducing to see if the panic
message differs between boots.


root on rd0a swap on rd0b dump on rd0b
uvm_fault(0xff011f73ac60, 0x208, 0, 1) -> e
fatal page fault in supervisor mode
trap type 6 code 0 rip 8135510b cs 8 rflags 10246 cr2 208 cpl
0 rsp 800022026c90
gsbase 0x81870ff0 kgsbase 0x0
panic: trap type 6, code=0, pc=8135510b
syncing disk... done

dump to dev 17,1 not possible
rebooting...


Hope this helps.

--david



bsd.rd failure in VirtualBox

2018-09-15 Thread David Higgs
I often use VirtualBox (version 5.2.18 on OS X) to familiarize myself
with new features in snapshots, before upgrading my physical hardware.

This afternoon, I tried updating bsd.rd (amd64, 6.4-beta RAMDISK_CD
#281) and wasn't able to successfully boot it.  I had to rely on the
video capture ability of VirtualBox to even notice there was a panic
(typed out below) before it rebooted to the "BIOS" splash screen.


Welcome to the OpenBSD/amd64 6.4 installation program.
fatal protection fault in supervisor mode
trap type 4 code 0 rip 810f24e4 cs 8 rflags 10206 cr2 6c1fed
cpl a rsp 800022098a10
gsbase 0x8186eff0 kgsbase 0x0
panic: trap type 4, code 0, pc=0x810f24e4
syncing disks... done

dump to dev 17,1 not possible
rebooting...


Also attached is the dmesg from a prior working snapshot.  I haven't
tried updating since this prior snapshot, so I don't have further
insight into when the issue first appeared.

--david
OpenBSD 6.4-beta (GENERIC) #250: Sun Aug 26 00:10:38 MDT 2018
dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC
real mem = 4278124544 (4079MB)
avail mem = 4139393024 (3947MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.5 @ 0xe1000 (10 entries)
bios0: vendor innotek GmbH version "VirtualBox" date 12/01/2006
bios0: innotek GmbH VirtualBox
acpi0 at bios0: rev 2
acpi0: sleep states S0 S5
acpi0: tables DSDT FACP APIC SSDT
acpi0: wakeup devices
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM) i5-6360U CPU @ 2.00GHz, 1962.87 MHz, 06-4e-03
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,PCLMUL,MWAIT,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AES,XSAVE,AVX,RDRAND,NXE,RDTSCP,LONG,LAHF,ABM,3DNOWP,ITSC,FSGSBASE,AVX2,INVPCID,RDSEED,CLFLUSHOPT,L1DF,MELTDOWN
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: CPU supports MTRRs but not enabled by BIOS
cpu0: apic clock running at 999MHz
cpu0: mwait min=64, max=64
ioapic0 at mainbus0: apid 1 pa 0xfec0, version 20, 24 pins, remapped
acpiprt0 at acpi0: bus 0 (PCI0)
acpicpu0 at acpi0: C1(@1 halt!)
acpibat0 at acpi0: BAT0 model "1" serial 0 type VBOX oem "innotek"
acpiac0 at acpi0: AC unit offline
acpivideo0 at acpi0: GFX0
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel 82441FX" rev 0x02
pcib0 at pci0 dev 1 function 0 "Intel 82371SB ISA" rev 0x00
pciide0 at pci0 dev 1 function 1 "Intel 82371AB IDE" rev 0x01: DMA, channel 0 
configured to compatibility, channel 1 configured to compatibility
wd0 at pciide0 channel 0 drive 0: 
wd0: 128-sector PIO, LBA, 20480MB, 41943040 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
atapiscsi0 at pciide0 channel 1 drive 0
scsibus1 at atapiscsi0: 2 targets
cd0 at scsibus1 targ 0 lun 0:  ATAPI 5/cdrom removable
cd0(pciide0:1:0): using PIO mode 4, Ultra-DMA mode 2
vga1 at pci0 dev 2 function 0 "InnoTek VirtualBox Graphics Adapter" rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
em0 at pci0 dev 3 function 0 "Intel 82540EM" rev 0x02: apic 1 int 19, address 
08:00:27:36:05:97
"InnoTek VirtualBox Guest Service" rev 0x00 at pci0 dev 4 function 0 not 
configured
piixpm0 at pci0 dev 7 function 0 "Intel 82371AB Power" rev 0x08: apic 1 int 23
iic0 at piixpm0
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
root on wd0a (4f192ba57dbd4eac.a) swap on wd0b dump on wd0b


Re: fix ld -Z on powerpc

2015-08-18 Thread David Higgs
On Tue, Aug 18, 2015 at 6:22 AM, Mark Kettenis mark.kette...@xs4all.nl
wrote:

  Date: Tue, 18 Aug 2015 05:03:19 +
  From: Miod Vallat m...@online.fr
 
   I spent some time today figuting out why the binutils update broke ld
   -Z on powerpc.  Turns out to be a fairly thorny issue.
  
   The new binutils discard empty setions.  As a result the .gotpad0 and
   .gotpad1 sections have disappeared.  And a s a consequence the
   __got_start and __got_end symbols are now absolute symbols as the
   section they referenced to is no longer there.  For example, an older
   libc has:
  
  845: 000eeb68 0 NOTYPE  GLOBAL DEFAULT   17 __got_start
  
   whereas -current has:
  
  810: 000eeb58 0 NOTYPE  GLOBAL DEFAULT  ABS __got_start
  
   On powerpc, crt0.o has weak references to __got_start and __got_end.
   When building a binary with ld -Z, these are resolved to the absolute
   symbols from libc.  At runtime we then use these values, relocated as
   if they were addresses within the binary itself, to change protections
   and flush the instruction cache.  This is very likely to result in a
   segmentation fault.
  
   There is probably a linker bug here, as it doesn't make any sense for
   the linker to pick the address of these symbols from libc and stick it
   into the binary.  But I'm not sure about this.  And it isn't all that
   obvious what the fix would be.  Is the bug that the symbols end up as
   absolute?  Or is the problem that it sibsequently resolves these to
   the values from libc.so?
 
  Wouldn't something like that address the problem better?

 Unfortunately not.  Using PROVIDE() makes the __got_start/end symbols
 disappear from shared libraries.  If I use:

   GOTSTART=__got_start = .;

 I end up with the same absolute symbols as before.  You really have
 to tie the symbols to a specific section that isn't discarded to make
 them end up as normal symbols.  And that is difficult since we try
 to make __got_start/end cover multiple sections, some of which may or
 may not be present.

 I still think my diff to remove code is the way to go.  As I
 explained, it isn't really clear which set of symbols the references
 in crt0.o will actually resolve to.  And the secure-plt work will
 require changes to the code anyway to make sure we don't end up with
 an executable GOT after all.

 Would KEEP statements in a linker script be a suitable workaround?

https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep

--david


upd(4) man page update

2015-06-25 Thread David Higgs
If there’s no further work on upd(4) prior to 5.8, at least make the man page 
reflect present reality.

- Update list of supported sensors, re-sorted by source file occurrence
- Explain why manual sensorsd.conf(5) intervention can be necessary
- Link to HID power specs
- Prefer “a UPS” over “an UPS”, matches HID docs above
- Other misc linguistic bikeshedding

Apologies, this is my first experience with mdoc(7).

--david

Index: upd.4
===
RCS file: /cvs/src/share/man/man4/upd.4,v
retrieving revision 1.3
diff -u -p -r1.3 upd.4
--- upd.4   19 Mar 2014 09:22:25 -  1.3
+++ upd.4   26 Jun 2015 02:46:15 -
@@ -25,17 +25,23 @@
 .Sh DESCRIPTION
 The
 .Nm
-driver exposes data from USB Power Devices (such as an UPS),
-as hardware sensors via
-.Xr sysctl 3 .
+driver provides support for monitoring various sensors provided by
+USB Power Devices (such as a UPS).
+Supported sensor values are made available via the
+.Xr sysctl 8 interface.
 .Pp
-The following sensors are provided by the
-.Nm
-driver, which can be monitored using
-.Xr sensorsd 8 :
+The following sensors are supported by the driver:
 .Pp
 .Bl -item -offset indent -compact
 .It
+BatteryPresent
+.It
+ShutdownImminent
+.It
+ACPresent
+.It
+Overload
+.It
 RelativeStateOfCharge
 .It
 AbsoluteStateOfCharge
@@ -48,19 +54,23 @@ Charging
 .It
 Discharging
 .It
-BatteryPresent
+AtRateTimeToFull
 .It
-ShutdownImminent
+AtRateTimeToEmpty
 .It
-ACPresent
+RunTimeToEmpty
 .It
-AtRateTimeToFull
+NeedReplacement
 .El
 .Sh SEE ALSO
 .Xr intro 4 ,
 .Xr uhidev 4 ,
 .Xr sensorsd 8 ,
+.Xr sensorsd.conf 5 ,
 .Xr sysctl 8
+.Pp
+The USB Power Devices specification can be found at
+.Lk http://www.usb.org/developers/hidpage/
 .Sh HISTORY
 The
 .Nm
@@ -71,3 +81,18 @@ The
 .Nm
 driver was written by
 .An Andre de Oliveira .
+.Sh BUGS
+The
+.Nm
+driver does not indicate device health via aggregate or
+individual sensor status.
+Users who wish to monitor
+.Nm
+status using
+.Xr sensorsd 8
+must manually establish
+.Dq high
+and
+.Dq low
+limits for sensor values of interest via
+.Xr sensorsd.conf 5 .




Re: Simple upd(4) sensors

2015-06-16 Thread David Higgs
On Wed, Jun 10, 2015 at 5:23 AM, Martin Pieuchot m...@openbsd.org wrote:

 On 02/06/15(Tue) 22:36, David Higgs wrote:
  Here are some new sensors for upd(4) devices.  All exist on my device
 except AtRateTimeToEmpty, which still seemed a logical addition given that
 AtRateTimeToFull is already present.
  - AtRateTimeToEmpty
  - RunTimeToEmpty
  - NeedReplacement
  - Overload

 Nice.

  If anyone had an AtRate sensor, it was probably producing meaningless
 output.  The relevant spec [0] indicates that these are in minutes, and my
 device appears to be using seconds; the (previously unscaled) sensor value
 expects nanoseconds!
  [0] http://www.usb.org/developers/hidpage/pdcv10.pdf
 
  And lastly, the NeedReplacement report has nothing to do with the System
 Management Bus (SMB), so rename the constant.  Nothing else in the tree
 appears to use it, so hopefully this is safe.
 
  Feedback and lsusb -v output is welcome, as usual.

 Have you got any feedback from upd(4) users?

 Update, someone was nice enough to test my diff, output below.  Looks
nearly identical to my own APC device, which isn't too surprising.

--david

 snip 

Sensors before

   $ sysctl hw.sensors.upd0
   hw.sensors.upd0.indicator0=On (BatteryPresent), OK
   hw.sensors.upd0.indicator1=On (Charging), OK
   hw.sensors.upd0.indicator2=Off (Discharging), OK
   hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
   hw.sensors.upd0.indicator4=On (ACPresent), OK
   hw.sensors.upd0.percent0=95.00% (RemainingCapacity), OK
   hw.sensors.upd0.percent1=100.00% (FullChargeCapacity), OK

and after

   $ sysctl hw.sensors.upd0
   hw.sensors.upd0.indicator0=On (BatteryPresent), OK
   hw.sensors.upd0.indicator1=On (Charging), OK
   hw.sensors.upd0.indicator2=Off (Discharging), OK
   hw.sensors.upd0.indicator3=Off (NeedReplacement), OK
   hw.sensors.upd0.indicator4=Off (ShutdownImminent), OK
   hw.sensors.upd0.indicator5=On (ACPresent), OK
   hw.sensors.upd0.indicator6=Off (Overload), OK
   hw.sensors.upd0.percent0=93.00% (RemainingCapacity), OK
   hw.sensors.upd0.percent1=100.00% (FullChargeCapacity), OK
   hw.sensors.upd0.timedelta0=1275.00 secs (RunTimeToEmpty), OK

$ dmesg | tail -n 3
uhidev2 at uhub2 port 4 configuration 1 interface 0 American Power
Conversion Back-UPS CS 500 FW:808.q8.I USB FW:q8 rev 1.10/0.06 addr 2
uhidev2: iclass 3/0, 98 report ids
upd0 at uhidev2


Re: Simple upd(4) sensors

2015-06-10 Thread David Higgs
On Wed, Jun 10, 2015 at 5:23 AM, Martin Pieuchot m...@openbsd.org wrote:

 On 02/06/15(Tue) 22:36, David Higgs wrote:
  Here are some new sensors for upd(4) devices.  All exist on my device
 except AtRateTimeToEmpty, which still seemed a logical addition given that
 AtRateTimeToFull is already present.
  - AtRateTimeToEmpty
  - RunTimeToEmpty
  - NeedReplacement
  - Overload

 Nice.

  If anyone had an AtRate sensor, it was probably producing meaningless
 output.  The relevant spec [0] indicates that these are in minutes, and my
 device appears to be using seconds; the (previously unscaled) sensor value
 expects nanoseconds!
  [0] http://www.usb.org/developers/hidpage/pdcv10.pdf
 
  And lastly, the NeedReplacement report has nothing to do with the System
 Management Bus (SMB), so rename the constant.  Nothing else in the tree
 appears to use it, so hopefully this is safe.
 
  Feedback and lsusb -v output is welcome, as usual.

 Have you got any feedback from upd(4) users?

 Not as of yet.

Theo reminded me that upd(4) usability needs to improve, so before I add
any more sensors I will next be looking into man page updates and/or
improved sensor status (e.g. WARN, CRITICAL) so that you need less
configuration voodoo to get useful behavior out of sensorsd(8).

Let me know if these new sensors should wait, in which case I can cut a
separate diff for the other fixes and build upon that instead.

--david


Simple upd(4) sensors

2015-06-02 Thread David Higgs
Here are some new sensors for upd(4) devices.  All exist on my device except 
AtRateTimeToEmpty, which still seemed a logical addition given that 
AtRateTimeToFull is already present.
- AtRateTimeToEmpty
- RunTimeToEmpty
- NeedReplacement
- Overload

If anyone had an AtRate sensor, it was probably producing meaningless output.  
The relevant spec [0] indicates that these are in minutes, and my device 
appears to be using seconds; the (previously unscaled) sensor value expects 
nanoseconds!
[0] http://www.usb.org/developers/hidpage/pdcv10.pdf

And lastly, the NeedReplacement report has nothing to do with the System 
Management Bus (SMB), so rename the constant.  Nothing else in the tree appears 
to use it, so hopefully this is safe.

Feedback and lsusb -v output is welcome, as usual.

--david

--- a/upd.c
+++ b/upd.c
@@ -66,7 +66,13 @@ static struct upd_usage_entry upd_usage_
{ HUP_BATTERY,  HUB_DISCHARGING,
SENSOR_INDICATOR,Discharging },
{ HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
-   SENSOR_TIMEDELTA,AtRateTimeToFull }
+   SENSOR_TIMEDELTA,AtRateTimeToFull },
+   { HUP_BATTERY,  HUB_ATRATE_TIMETOEMPTY,
+   SENSOR_TIMEDELTA,AtRateTimeToEmpty },
+   { HUP_BATTERY,  HUB_RUNTIMETO_EMPTY,
+   SENSOR_TIMEDELTA,RunTimeToEmpty },
+   { HUP_BATTERY,  HUB_NEED_REPLACEMENT,
+   SENSOR_INDICATOR,NeedReplacement },
 };
 static struct upd_usage_entry upd_usage_roots[] = {
{ HUP_BATTERY,  HUB_BATTERY_PRESENT,
@@ -75,7 +81,9 @@ static struct upd_usage_entry upd_usage_
{ HUP_POWER,HUP_SHUTDOWN_IMMINENT,
SENSOR_INDICATOR,ShutdownImminent },
{ HUP_BATTERY,  HUB_AC_PRESENT,
-   SENSOR_INDICATOR,ACPresent }
+   SENSOR_INDICATOR,ACPresent },
+   { HUP_POWER,HUP_OVERLOAD,
+   SENSOR_INDICATOR,Overload },
 };
 #define UPD_MAX_SENSORS(nitems(upd_usage_batdep) + 
nitems(upd_usage_roots))
 
@@ -410,6 +418,12 @@ upd_sensor_update(struct upd_softc *sc,
case HUB_FULLCHARGE_CAPACITY:
adjust = 1000; /* scale adjust */
break;
+   case HUB_ATRATE_TIMETOFULL:
+   case HUB_ATRATE_TIMETOEMPTY:
+   case HUB_RUNTIMETO_EMPTY:
+   /* spec says minutes, not seconds */
+   adjust = 10LL;
+   break;
default:
adjust = 1; /* no scale adjust */
break;
--- a/usbhid.h
+++ b/usbhid.h
@@ -213,7 +213,7 @@ struct usb_hid_descriptor {
 #define HUB_CONDITIONING_FLAG  0x0048
 #define HUB_ATRATE_OK  0x0049
 #define HUB_SMB_ERROR_CODE 0x004a
-#define HUB_SMB_NEED_REPLACE   0x004b
+#define HUB_NEED_REPLACEMENT   0x004b
 #define HUB_ATRATE_TIMETOFULL  0x0060
 #define HUB_ATRATE_TIMETOEMPTY 0x0061
 #define HUB_AVERAGE_CURRENT0x0062




Re: UPD regression with

2015-05-12 Thread David Higgs
On May 11, 2015, at 9:02 PM, David Higgs hig...@gmail.com wrote:
 
 On May 11, 2015, at 8:21 PM, David Higgs hig...@gmail.com 
 mailto:hig...@gmail.com wrote:
 
 On Mon, May 11, 2015 at 8:07 PM, Alexander Hall alexan...@beard.se 
 mailto:alexan...@beard.sewrote:
 Upgrading to the latest snapshot, I noticed my upd sensors had been
 disturbingly crippled.
 
  uhidev0 at uhub4 port 1 configuration 1 interface 0 EATON Eaton 3S rev 
 2.00/1.00 addr 2
  uhidev0: iclass 3/0, 32 report ids
  upd0 at uhidev0
 
 Diff below is what happens from upd.c r1.13 to r1.14.
 
 -hw.sensors.upd0.indicator0=On (ACPresent), OK
 -hw.sensors.upd0.indicator1=On (Charging), OK
 -hw.sensors.upd0.indicator2=Off (Discharging), OK
 -hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
 -hw.sensors.upd0.percent0=100.00% (FullChargeCapacity), OK
 -hw.sensors.upd0.percent1=100.00% (RemainingCapacity), OK
 +hw.sensors.upd0.indicator0=Off (ShutdownImminent), OK
 +hw.sensors.upd0.indicator1=On (ACPresent), OK
 
 Is this an expected fallout? Can I provide more info to assist? Full
 dmesg (latest snap + vanilla current kernel w/ upd.c r1.13) follows. 
 
 It seems your device doesn't have a BatteryPresent report, or it is somehow 
 getting mangled.  Can you run lsusb -v on your device and check if Battery 
 Present is shown?
 
 If it is not, we'll have to make sensor dependencies less strict.  I'll 
 start thinking about how to do this.
 
 Alternatively, you could try the following diff, which flattens the sensor 
 dependency tree when a parent sensor isn’t available.

Below is a diff which has the correct number of parentheses and actually 
compiles.  Sorry for the noise.

--david

--- a/upd.c
+++ b/upd.c
@@ -225,8 +225,12 @@ upd_attach_sensor_tree(struct upd_softc
 
for (i = 0; i  nentries; i++) {
entry = entries + i;
-   if (!upd_lookup_usage_entry(desc, size, entry, item))
+   if (!upd_lookup_usage_entry(desc, size, entry, item)) {
+   /* dependency missing, add children to parent */
+   upd_attach_sensor_tree(sc, desc, size,
+   entry-nchildren, entry-children, queue);
continue;
+   }
 
DPRINTF((%s: found %s on repid=%d\n, DEVNAME(sc),
entry-usage_name, item.report_ID));




Re: UPD regression with

2015-05-11 Thread David Higgs
On Mon, May 11, 2015 at 8:07 PM, Alexander Hall alexan...@beard.se wrote:

 Upgrading to the latest snapshot, I noticed my upd sensors had been
 disturbingly crippled.

  uhidev0 at uhub4 port 1 configuration 1 interface 0 EATON Eaton 3S rev
 2.00/1.00 addr 2
  uhidev0: iclass 3/0, 32 report ids
  upd0 at uhidev0

 Diff below is what happens from upd.c r1.13 to r1.14.

 -hw.sensors.upd0.indicator0=On (ACPresent), OK
 -hw.sensors.upd0.indicator1=On (Charging), OK
 -hw.sensors.upd0.indicator2=Off (Discharging), OK
 -hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
 -hw.sensors.upd0.percent0=100.00% (FullChargeCapacity), OK
 -hw.sensors.upd0.percent1=100.00% (RemainingCapacity), OK
 +hw.sensors.upd0.indicator0=Off (ShutdownImminent), OK
 +hw.sensors.upd0.indicator1=On (ACPresent), OK

 Is this an expected fallout? Can I provide more info to assist? Full
 dmesg (latest snap + vanilla current kernel w/ upd.c r1.13) follows.


It seems your device doesn't have a BatteryPresent report, or it is somehow
getting mangled.  Can you run lsusb -v on your device and check if Battery
Present is shown?

If it is not, we'll have to make sensor dependencies less strict.  I'll
start thinking about how to do this.

Thanks for the report.

--david


Re: UPD regression with

2015-05-11 Thread David Higgs

 On May 11, 2015, at 8:21 PM, David Higgs hig...@gmail.com wrote:
 
 On Mon, May 11, 2015 at 8:07 PM, Alexander Hall alexan...@beard.se 
 mailto:alexan...@beard.sewrote:
 Upgrading to the latest snapshot, I noticed my upd sensors had been
 disturbingly crippled.
 
  uhidev0 at uhub4 port 1 configuration 1 interface 0 EATON Eaton 3S rev 
 2.00/1.00 addr 2
  uhidev0: iclass 3/0, 32 report ids
  upd0 at uhidev0
 
 Diff below is what happens from upd.c r1.13 to r1.14.
 
 -hw.sensors.upd0.indicator0=On (ACPresent), OK
 -hw.sensors.upd0.indicator1=On (Charging), OK
 -hw.sensors.upd0.indicator2=Off (Discharging), OK
 -hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
 -hw.sensors.upd0.percent0=100.00% (FullChargeCapacity), OK
 -hw.sensors.upd0.percent1=100.00% (RemainingCapacity), OK
 +hw.sensors.upd0.indicator0=Off (ShutdownImminent), OK
 +hw.sensors.upd0.indicator1=On (ACPresent), OK
 
 Is this an expected fallout? Can I provide more info to assist? Full
 dmesg (latest snap + vanilla current kernel w/ upd.c r1.13) follows. 
 
 It seems your device doesn't have a BatteryPresent report, or it is somehow 
 getting mangled.  Can you run lsusb -v on your device and check if Battery 
 Present is shown?
 
 If it is not, we'll have to make sensor dependencies less strict.  I'll start 
 thinking about how to do this.

Alternatively, you could try the following diff, which flattens the sensor 
dependency tree when a parent sensor isn’t available.

Thanks.

--david

--- a/upd.c
+++ b/upd.c
@@ -225,8 +225,12 @@ upd_attach_sensor_tree(struct upd_softc
 
for (i = 0; i  nentries; i++) {
entry = entries + i;
-   if (!upd_lookup_usage_entry(desc, size, entry, item))
+   if (!upd_lookup_usage_entry(desc, size, entry, item) {
+   /* dependency missing, add children to parent */
+   upd_attach_sensor_tree(sc, desc, size,
+   entry-nchildren, entry-children, queue);
continue;
+   }
 
DPRINTF((%s: found %s on repid=%d\n, DEVNAME(sc),
entry-usage_name, item.report_ID));



Re: Async upd(4) - patch 7/7

2015-05-06 Thread David Higgs

 On Apr 30, 2015, at 7:09 AM, Martin Pieuchot m...@openbsd.org wrote:
 
 On 24/04/15(Fri) 20:48, David Higgs wrote:
 This is the final patch in the series.
 
 Utilize the pending flags and report callback for their intended purpose - 
 to process async behavior.
 
 Apply splusb() to ensure report callbacks can't fire before their data 
 structures have been properly updated.  This only needs to happen in 
 upd_refresh(); all other calls to upd_request_children() are from a report 
 callback.
 
 This is some good work.  I don't think your patch #6 makes sense without
 #7, so I merged them.
 
 I don't think you need a pending flags for the sensors, since what you
 are querying are the reports.  You basically do not want to send to
 requests for the same report at once.
 

I still disagree.  However, the fix for this isn’t difficult and can be handled 
in a future diff.

 I'd also take the simpler approach of not deactivating all sensors if
 you fail to *submit* a transfer.  When such thing happens it's either
 because the device/bus is going away or because we cannot allocate
 memory.
 
Even in these situations, invalidating all affected sensors seems an easy and 
consistent thing to do.

 I tweaked your diff below, included some comments and your copyright.
 This is untested but I hope you'll correct/improve it.
 

Your tweaks were good, so I tweaked it further:
- When submit fails, invalidate affected sensors as described above.
- When invalidating sensors, do it recursively.
- When battery is not present, invalidate children but not BatteryPresent.

Let me know what you think.

--david

--- a/upd.c
+++ b/upd.c
@@ -1,6 +1,7 @@
 /* $OpenBSD: upd.c,v 1.19 2015/04/30 10:09:31 mpi Exp $ */
 
 /*
+ * Copyright (c) 2015 David Higgs hig...@gmail.com
  * Copyright (c) 2014 Andre de Oliveira an...@openbsd.org
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -78,25 +79,28 @@ static struct upd_usage_entry upd_usage_
 };
 #define UPD_MAX_SENSORS(nitems(upd_usage_batdep) + 
nitems(upd_usage_roots))
 
+SLIST_HEAD(upd_sensor_head, upd_sensor);
+
 struct upd_report {
-   size_t  size;
-   SLIST_HEAD(, upd_sensor)sensors;
+   size_t  size;   /* Size of the report */
+   struct upd_sensor_head  sensors;/* List in dependency order */
+   int pending;/* Waiting for an answer */
 };
 
-SLIST_HEAD(upd_sensor_head, upd_sensor);
 struct upd_sensor {
-   struct ksensor  ksensor;
-   struct hid_item hitem;
-   int attached;
-   struct upd_sensor_head  children;
-   SLIST_ENTRY(upd_sensor) dep_next;
-   SLIST_ENTRY(upd_sensor) rep_next;
+   struct ksensor  ksensor;
+   struct hid_item hitem;
+   int attached;   /* Is there a matching report */
+   struct upd_sensor_head  children;   /* list of children sensors */
+   SLIST_ENTRY(upd_sensor) dep_next;   /* next in the child list */
+   SLIST_ENTRY(upd_sensor) rep_next;   /* next in the report list */
 };
 
 struct upd_softc {
struct uhidevsc_hdev;
int  sc_num_sensors;
u_intsc_max_repid;
+   char sc_buf[256];
 
/* sensor framework */
struct ksensordevsc_sensordev;
@@ -112,11 +116,13 @@ void upd_attach_sensor_tree(struct upd_s
 struct upd_usage_entry *, struct upd_sensor_head *);
 int  upd_detach(struct device *, int);
 
-void upd_refresh(void *);
-void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
-void upd_update_sensor_value(struct upd_softc *, struct upd_sensor *,
-uint8_t *, int);
 void upd_intr(struct uhidev *, void *, uint);
+void upd_refresh(void *);
+void upd_request_children(struct upd_softc *, struct upd_sensor_head *);
+void upd_update_report_cb(void *, int, void *, int);
+
+void upd_sensor_invalidate(struct upd_softc *, struct upd_sensor *);
+void upd_sensor_update(struct upd_softc *, struct upd_sensor *, uint8_t *, 
int);
 int upd_lookup_usage_entry(void *, int, struct upd_usage_entry *,
 struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
@@ -126,10 +132,7 @@ struct cfdriver upd_cd = {
 };
 
 const struct cfattach upd_ca = {
-   sizeof(struct upd_softc),
-   upd_match,
-   upd_attach,
-   upd_detach
+   sizeof(struct upd_softc), upd_match, upd_attach, upd_detach
 };
 
 int
@@ -273,42 +276,50 @@ upd_detach(struct device *self, int flag
sensor = sc-sc_sensors[i];
if (sensor-attached)
sensor_detach(sc-sc_sensordev, sensor-ksensor);
-   DPRINTF((upd_detach: %s\n, sensor-ksensor.desc));
}
 
free(sc-sc_reports, M_USBDEV, 0);
free(sc

Re: Async upd(4) - patch 7/7

2015-04-30 Thread David Higgs
On Thu, Apr 30, 2015 at 7:09 AM, Martin Pieuchot m...@openbsd.org wrote:

 On 24/04/15(Fri) 20:48, David Higgs wrote:
  This is the final patch in the series.
 
  Utilize the pending flags and report callback for their intended purpose
 - to process async behavior.
 
  Apply splusb() to ensure report callbacks can't fire before their data
 structures have been properly updated.  This only needs to happen in
 upd_refresh(); all other calls to upd_request_children() are from a report
 callback.

 This is some good work.  I don't think your patch #6 makes sense without
 #7, so I merged them.


Sounds good, thanks for all the help.

I don't think you need a pending flags for the sensors, since what you
 are querying are the reports.  You basically do not want to send to
 requests for the same report at once.


In general the code tries to avoid requesting reports more than once, but
this prevents sensor dependencies from causing some nasty problems.  In the
example below, I don't want the update of C to re-update A and trigger an
infinite loop by requesting B.

Sensor A (report 1) - Sensor B (report 2) - Sensor C (report 1)

The alternative is to allow inconsistent sensor values.  If the value of B
affects the value of C, I would rather perform a 2nd request for report 1
once I have the value of B, than to put garbage/bogus values into C.

I prefer to keep sensor values consistent, to ensure nobody's sensorsd
starts to panic and because I doubt many real devices have this kind of
annoying HID descriptor layout.


 I'd also take the simpler approach of not deactivating all sensors if
 you fail to *submit* a transfer.  When such thing happens it's either
 because the device/bus is going away or because we cannot allocate
 memory.


This sounds fine for the bus/device case or if M_NOWAIT would trigger a
panic.  How about if the usb device itself runs out of memory/buffers; will
the rest of the system stay happy?  Again, I prefer to err on the side of
consistency and invalidate child sensors so sensorsd isn't looking at stale
values.


 I tweaked your diff below, included some comments and your copyright.
 This is untested but I hope you'll correct/improve it.


I'll take a look over the next week.


 I'm also curious, which new reports/sensors do you want to add?


I haven't looked at this in some months.  My consumer-grade device had
several useful sensors that aren't currently handled.  There are some
internal reports (CapacityMode, AtRate) that aren't suitable as sensors,
but might fix other sensor values being mis-reported.  And there are
interactive things that can be done via reports - silencing the audible
alarm, requesting self-tests - that would be good as sysctls or ioctls
someday.

I'll be happy to look at lsusb output if anyone has a device in mind.

Thanks.

--david


Re: Map upd(4) sensors to reports

2015-04-24 Thread David Higgs
On Fri, Apr 24, 2015 at 8:43 PM, David Higgs hig...@gmail.com wrote:

 Associate sensors with the reports they are updated by.  Only the reports
 that have sensors will be enabled, so the enabled field becomes redundant.

 An important but subtle side-effect is that because the sensor tree is
 constructed depth-first, each report SLIST will contain sensors in
 dependency order.


This is patch 5/7, by the way.


Map upd(4) sensors to reports

2015-04-24 Thread David Higgs
Associate sensors with the reports they are updated by.  Only the reports that 
have sensors will be enabled, so the enabled field becomes redundant.

An important but subtle side-effect is that because the sensor tree is 
constructed depth-first, each report SLIST will contain sensors in dependency 
order.

--david

--- a/upd.c
+++ b/upd.c
@@ -79,8 +79,8 @@ static struct upd_usage_entry upd_usage_
 #define UPD_MAX_SENSORS(nitems(upd_usage_batdep) + 
nitems(upd_usage_roots))
 
 struct upd_report {
-   size_t  size;
-   int enabled;
+   size_t  size;
+   SLIST_HEAD(, upd_sensor)sensors;
 };
 
 SLIST_HEAD(upd_sensor_head, upd_sensor);
@@ -90,6 +90,7 @@ struct upd_sensor {
int attached;
struct upd_sensor_head  children;
SLIST_ENTRY(upd_sensor) dep_next;
+   SLIST_ENTRY(upd_sensor) rep_next;
 };
 
 struct upd_softc {
@@ -183,6 +184,8 @@ upd_attach(struct device *parent, struct
 
sc-sc_reports = mallocarray(sc-sc_max_repid,
sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO);
+   for (i = 0; i  sc-sc_max_repid; i++)
+   SLIST_INIT(sc-sc_reports[i].sensors);
sc-sc_sensors = mallocarray(UPD_MAX_SENSORS,
sizeof(struct upd_sensor), M_USBDEV, M_WAITOK | M_ZERO);
for (i = 0; i  UPD_MAX_SENSORS; i++)
@@ -214,6 +217,7 @@ upd_attach_sensor_tree(struct upd_softc
struct hid_item   item;
struct upd_usage_entry   *entry;
struct upd_sensor*sensor;
+   struct upd_report*report;
int   i;
 
for (i = 0; i  nentries; i++) {
@@ -243,11 +247,11 @@ upd_attach_sensor_tree(struct upd_softc
upd_attach_sensor_tree(sc, desc, size, entry-nchildren,
entry-children, sensor-children);
 
-   if (sc-sc_reports[item.report_ID].enabled)
-   continue;
-   sc-sc_reports[item.report_ID].size = hid_report_size(desc,
-   size, item.kind, item.report_ID);
-   sc-sc_reports[item.report_ID].enabled = 1;
+   report = sc-sc_reports[item.report_ID];
+   if (SLIST_EMPTY(report-sensors))
+   report-size = hid_report_size(desc,
+   size, item.kind, item.report_ID);
+   SLIST_INSERT_HEAD(report-sensors, sensor, rep_next);
}
 }
 
@@ -288,7 +292,7 @@ upd_refresh(void *arg)
 
for (repid = 0; repid  sc-sc_max_repid; repid++) {
report = sc-sc_reports[repid];
-   if (!report-enabled)
+   if (SLIST_EMPTY(report-sensors))
continue;
 
memset(buf, 0x0, sizeof(buf));




Async upd(4) - patch 7/7

2015-04-24 Thread David Higgs
This is the final patch in the series.

Utilize the pending flags and report callback for their intended purpose - to 
process async behavior.

Apply splusb() to ensure report callbacks can't fire before their data 
structures have been properly updated.  This only needs to happen in 
upd_refresh(); all other calls to upd_request_children() are from a report 
callback.

--david

--- a/upd.c
+++ b/upd.c
@@ -99,6 +99,7 @@ struct upd_softc {
struct uhidevsc_hdev;
int  sc_num_sensors;
u_intsc_max_repid;
+   char sc_buf[256];
 
/* sensor framework */
struct ksensordevsc_sensordev;
@@ -290,27 +291,12 @@ void
 upd_refresh(void *arg)
 {
struct upd_softc*sc = arg;
-   struct upd_report   *report;
-   uint8_t buf[256];
-   int repid, actlen, done;
+   int  s;
 
-   /* request root sensors */
+   /* request root sensors, do not let async handlers fire yet */
+   s = splusb();
upd_request_children(sc, sc-sc_root_sensors, 1);
-
-   /* repeat until all reports queried */
-   do {
-   done = 1;
-   for (repid = 0; repid  sc-sc_max_repid; repid++) {
-   report = sc-sc_reports[repid];
-   if (!report-pending)
-   continue;
-   memset(buf, 0x0, sizeof(buf));
-   actlen = uhidev_get_report(sc-sc_hdev.sc_parent,
-   UHID_FEATURE_REPORT, repid, buf, report-size);
-   upd_update_report_cb(sc, repid, buf, actlen);
-   done = 0;
-   }
-   } while (!done);
+   splx(s);
 }
 
 void
@@ -336,7 +322,14 @@ upd_request_children(struct upd_softc *s
} else if (report-pending)
/* already requested */
sensor-pending = 1;
-   else {
+   else if (uhidev_get_report_async(sc-sc_hdev.sc_parent,
+   UHID_FEATURE_REPORT, repid, sc-sc_buf,
+   report-size, sc, upd_update_report_cb)  0) {
+   DPRINTF((%s: %s request of repid %d failed\n,
+   DEVNAME(sc), sensor-ksensor.desc, repid));
+   sensor-pending = 1;
+   upd_update_report_cb(sc, repid, NULL, -1);
+   } else {
DPRINTF((%s: %s requests repid %d\n,
DEVNAME(sc), sensor-ksensor.desc, repid));
sensor-pending = 1;




upd(4) sensor lookup order - patch 3/7

2015-04-24 Thread David Higgs
Locate sensors in table order - by parsing the USB descriptor multiple times - 
instead of in the order they exist in the USB descriptor.

This will greatly ease construction of a sensor dependency tree, in the next 
diff.

--david

--- a/upd.c
+++ b/upd.c
@@ -86,7 +86,6 @@ struct upd_softc {
struct uhidevsc_hdev;
int  sc_num_sensors;
u_intsc_max_repid;
-   u_intsc_max_sensors;
 
/* sensor framework */
struct ksensordevsc_sensordev;
@@ -104,7 +103,8 @@ void upd_update_sensors(struct upd_softc
 void upd_update_sensor_value(struct upd_softc *, struct upd_sensor *,
 uint8_t *, int);
 void upd_intr(struct uhidev *, void *, uint);
-struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
+int upd_lookup_usage_entry(void *, int, struct upd_usage_entry *,
+struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
 
 struct cfdriver upd_cd = {
@@ -124,9 +124,9 @@ upd_match(struct device *parent, void *m
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
int   size;
void *desc;
-   struct hid_data  *hdata;
struct hid_item   item;
int   ret = UMATCH_NONE;
+   int   i;
 
if (uha-reportid != UHIDEV_CLAIM_ALLREPORTID)
return (ret);
@@ -138,14 +138,12 @@ upd_match(struct device *parent, void *m
 * look for at least one sensor of our table
 */
uhidev_get_report_desc(uha-parent, desc, size);
-   for (hdata = hid_start_parse(desc, size, hid_feature);
-hid_get_item(hdata, item); ) {
-   if (upd_lookup_usage_entry(item) != NULL) {
+   for (i = 0; i  nitems(upd_usage_table); i++)
+   if (upd_lookup_usage_entry(desc, size,
+   upd_usage_table + i, item)) {
ret = UMATCH_VENDOR_PRODUCT;
break;
}
-   }
-   hid_end_parse(hdata);
 
return (ret);
 }
@@ -156,17 +154,16 @@ upd_attach(struct device *parent, struct
struct upd_softc *sc = (struct upd_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
struct hid_item   item;
-   struct hid_data  *hdata;
struct upd_usage_entry   *entry;
struct upd_sensor*sensor;
int   size;
+   int   i;
void *desc;
 
sc-sc_hdev.sc_intr = upd_intr;
sc-sc_hdev.sc_parent = uha-parent;
sc-sc_reports = NULL;
sc-sc_sensors = NULL;
-   sc-sc_max_sensors = nitems(upd_usage_table);
 
strlcpy(sc-sc_sensordev.xname, DEVNAME(sc),
sizeof(sc-sc_sensordev.xname));
@@ -177,27 +174,20 @@ upd_attach(struct device *parent, struct
 
sc-sc_reports = mallocarray(sc-sc_max_repid,
sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO);
-   sc-sc_sensors = mallocarray(sc-sc_max_sensors,
+   sc-sc_sensors = mallocarray(nitems(upd_usage_table),
sizeof(struct upd_sensor), M_USBDEV, M_WAITOK | M_ZERO);
-   size = sc-sc_max_sensors * sizeof(struct upd_sensor);
sc-sc_num_sensors = 0;
-   uhidev_get_report_desc(uha-parent, desc, size);
-   for (hdata = hid_start_parse(desc, size, hid_feature);
-hid_get_item(hdata, item) 
-sc-sc_num_sensors  sc-sc_max_sensors; ) {
-   DPRINTF((upd: repid=%d\n, item.report_ID));
-   if (item.kind != hid_feature ||
-   item.report_ID  0 ||
-   item.report_ID = sc-sc_max_repid)
-   continue;
 
-   if ((entry = upd_lookup_usage_entry(item)) == NULL)
+   uhidev_get_report_desc(uha-parent, desc, size);
+   for (i = 0; i  nitems(upd_usage_table); i++) {
+   entry = upd_usage_table[i];
+   if (!upd_lookup_usage_entry(desc, size, entry, item))
continue;
 
-   /* filter repeated usages, avoid duplicated sensors */
-   sensor = upd_lookup_sensor(sc, entry-usage_pg,
-   entry-usage_id);
-   if (sensor != NULL)
+   DPRINTF((%s: found %s on repid=%d\n, DEVNAME(sc),
+   entry-usage_name, item.report_ID));
+   if (item.report_ID  0 ||
+   item.report_ID = sc-sc_max_repid)
continue;
 
sensor = sc-sc_sensors[sc-sc_num_sensors];
@@ -219,7 +209,6 @@ upd_attach(struct device *parent, struct
size, item.kind, item.report_ID);
sc-sc_reports[item.report_ID].enabled = 1;
}
-   hid_end_parse(hdata);
DPRINTF((upd: sc_num_sensors=%d\n, sc-sc_num_sensors));
 

upd(4) patchset

2015-04-24 Thread David Higgs
Huge thanks to all devs who provided initial feedback in spite of my
inconsistent development pace, especially mpi.

This was mainly a bugfix/infrastructure effort.  There's still plenty of
work to do on new features - better sensor units, new sensors, maybe some
sysctls.

Happy to accept bug reports, comments, questions, and feedback.
Meta-feedback is good too - patches too small/crappy, coding style
requests, etc.

--david


upd(4) sensor value - patch 2/7

2015-04-24 Thread David Higgs
Split out sensor value update now, since sensor updating will become more 
complex.

Also, avoid potential signed/unsigned and truncation errors.  Sensor values are 
int64_t wide, so put them to work.

--david

--- a/upd.c
+++ b/upd.c
@@ -101,6 +101,8 @@ int  upd_detach(struct device *, int);
 
 void upd_refresh(void *);
 void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
+void upd_update_sensor_value(struct upd_softc *, struct upd_sensor *,
+uint8_t *, int);
 void upd_intr(struct uhidev *, void *, uint);
 struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
@@ -324,8 +326,7 @@ upd_update_sensors(struct upd_softc *sc,
 int repid)
 {
struct upd_sensor   *sensor;
-   ulong   hdata, batpres;
-   ulong   adjust;
+   ulong   batpres;
int i;
 
sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT);
@@ -348,27 +349,35 @@ upd_update_sensors(struct upd_softc *sc,
}
}
 
-   switch (HID_GET_USAGE(sensor-hitem.usage)) {
-   case HUB_REL_STATEOF_CHARGE:
-   case HUB_ABS_STATEOF_CHARGE:
-   case HUB_REM_CAPACITY:
-   case HUB_FULLCHARGE_CAPACITY:
-   adjust = 1000; /* scale adjust */
-   break;
-   default:
-   adjust = 1; /* no scale adjust */
-   break;
-   }
+   upd_update_sensor_value(sc, sensor, buf, len);
+   }
+}
 
-   hdata = hid_get_data(buf, len, sensor-hitem.loc);
+void
+upd_update_sensor_value(struct upd_softc *sc, struct upd_sensor *sensor,
+uint8_t *buf, int len)
+{
+   int64_t hdata, adjust;
 
-   sensor-ksensor.value = hdata * adjust;
-   sensor-ksensor.status = SENSOR_S_OK;
-   sensor-ksensor.flags = ~SENSOR_FINVALID;
-   DPRINTF((%s: hidget data: %lu\n, DEVNAME(sc), hdata));
+   switch (HID_GET_USAGE(sensor-hitem.usage)) {
+   case HUB_REL_STATEOF_CHARGE:
+   case HUB_ABS_STATEOF_CHARGE:
+   case HUB_REM_CAPACITY:
+   case HUB_FULLCHARGE_CAPACITY:
+   adjust = 1000; /* scale adjust */
+   break;
+   default:
+   adjust = 1; /* no scale adjust */
+   break;
}
-}
 
+   hdata = hid_get_data(buf, len, sensor-hitem.loc);
+   sensor-ksensor.value = hdata * adjust;
+   sensor-ksensor.status = SENSOR_S_OK;
+   sensor-ksensor.flags = ~SENSOR_FINVALID;
+   DPRINTF((%s: %s hidget data: %lld\n, DEVNAME(sc),
+   sensor-ksensor.desc, hdata));
+}
 
 void
 upd_intr(struct uhidev *uh, void *p, uint len)




DEVNAME for upd(4) - patch 1/7

2015-04-24 Thread David Higgs
Should be pretty straightforward.

--david

--- a/upd.c
+++ b/upd.c
@@ -39,6 +39,8 @@
 #define DPRINTF(x)
 #endif
 
+#define DEVNAME(sc)((sc)-sc_hdev.sc_dev.dv_xname)
+
 struct upd_usage_entry {
uint8_t usage_pg;
uint8_t usage_id;
@@ -164,12 +166,12 @@ upd_attach(struct device *parent, struct
sc-sc_sensors = NULL;
sc-sc_max_sensors = nitems(upd_usage_table);
 
-   strlcpy(sc-sc_sensordev.xname, sc-sc_hdev.sc_dev.dv_xname,
+   strlcpy(sc-sc_sensordev.xname, DEVNAME(sc),
sizeof(sc-sc_sensordev.xname));
 
sc-sc_max_repid = uha-parent-sc_nrepid;
DPRINTF((\nupd: devname=%s sc_max_repid=%d\n,
-   sc-sc_hdev.sc_dev.dv_xname, sc-sc_max_repid));
+   DEVNAME(sc), sc-sc_max_repid));
 
sc-sc_reports = mallocarray(sc-sc_max_repid,
sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO);
@@ -363,8 +365,7 @@ upd_update_sensors(struct upd_softc *sc,
sensor-ksensor.value = hdata * adjust;
sensor-ksensor.status = SENSOR_S_OK;
sensor-ksensor.flags = ~SENSOR_FINVALID;
-   DPRINTF((%s: hidget data: %lu\n,
-   sc-sc_sensordev.xname, hdata));
+   DPRINTF((%s: hidget data: %lu\n, DEVNAME(sc), hdata));
}
 }
 



Build upd(4) sensor tree - patch 4/7

2015-04-24 Thread David Higgs
Divide sensors into two tables - normal sensors and battery dependent sensors.  
Build the sensor dependency tree - every sensor has an SLIST of dependent 
children.

Also, don’t bother looking for battery dependent sensors at device attach, it 
doesn’t seem helpful.

(Someone please correct me if static structure elements aren’t initialized to 
zero.)

--david

--- a/upd.c
+++ b/upd.c
@@ -23,6 +23,7 @@
 #include sys/kernel.h
 #include sys/malloc.h
 #include sys/device.h
+#include sys/queue.h
 #include sys/sensors.h
 
 #include dev/usb/hid.h
@@ -46,9 +47,11 @@ struct upd_usage_entry {
uint8_t usage_id;
enum sensor_typesenstype;
char*usage_name; /* sensor string */
+   int nchildren;
+   struct upd_usage_entry  *children;
 };
 
-static struct upd_usage_entry upd_usage_table[] = {
+static struct upd_usage_entry upd_usage_batdep[] = {
{ HUP_BATTERY,  HUB_REL_STATEOF_CHARGE,
SENSOR_PERCENT,  RelativeStateOfCharge },
{ HUP_BATTERY,  HUB_ABS_STATEOF_CHARGE,
@@ -61,25 +64,32 @@ static struct upd_usage_entry upd_usage_
SENSOR_INDICATOR,Charging },
{ HUP_BATTERY,  HUB_DISCHARGING,
SENSOR_INDICATOR,Discharging },
+   { HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
+   SENSOR_TIMEDELTA,AtRateTimeToFull }
+};
+static struct upd_usage_entry upd_usage_roots[] = {
{ HUP_BATTERY,  HUB_BATTERY_PRESENT,
-   SENSOR_INDICATOR,BatteryPresent },
+   SENSOR_INDICATOR,BatteryPresent,
+   nitems(upd_usage_batdep),   upd_usage_batdep },
{ HUP_POWER,HUP_SHUTDOWN_IMMINENT,
SENSOR_INDICATOR,ShutdownImminent },
{ HUP_BATTERY,  HUB_AC_PRESENT,
-   SENSOR_INDICATOR,ACPresent },
-   { HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
-   SENSOR_TIMEDELTA,AtRateTimeToFull }
+   SENSOR_INDICATOR,ACPresent }
 };
+#define UPD_MAX_SENSORS(nitems(upd_usage_batdep) + 
nitems(upd_usage_roots))
 
 struct upd_report {
size_t  size;
int enabled;
 };
 
+SLIST_HEAD(upd_sensor_head, upd_sensor);
 struct upd_sensor {
-   struct ksensor  ksensor;
-   struct hid_item hitem;
-   int attached;
+   struct ksensor  ksensor;
+   struct hid_item hitem;
+   int attached;
+   struct upd_sensor_head  children;
+   SLIST_ENTRY(upd_sensor) dep_next;
 };
 
 struct upd_softc {
@@ -92,10 +102,13 @@ struct upd_softc {
struct sensor_task  *sc_sensortask;
struct upd_report   *sc_reports;
struct upd_sensor   *sc_sensors;
+   struct upd_sensor_head   sc_root_sensors;
 };
 
 int  upd_match(struct device *, void *, void *);
 void upd_attach(struct device *, struct device *, void *);
+void upd_attach_sensor_tree(struct upd_softc *, void *, int, int,
+struct upd_usage_entry *, struct upd_sensor_head *);
 int  upd_detach(struct device *, int);
 
 void upd_refresh(void *);
@@ -134,13 +147,11 @@ upd_match(struct device *parent, void *m
DPRINTF((upd: vendor=0x%04x, product=0x%04x\n, uha-uaa-vendor,
uha-uaa-product));
 
-   /*
-* look for at least one sensor of our table
-*/
+   /* need at least one sensor from root of tree */
uhidev_get_report_desc(uha-parent, desc, size);
-   for (i = 0; i  nitems(upd_usage_table); i++)
+   for (i = 0; i  nitems(upd_usage_roots); i++)
if (upd_lookup_usage_entry(desc, size,
-   upd_usage_table + i, item)) {
+   upd_usage_roots + i, item)) {
ret = UMATCH_VENDOR_PRODUCT;
break;
}
@@ -153,9 +164,6 @@ upd_attach(struct device *parent, struct
 {
struct upd_softc *sc = (struct upd_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
-   struct hid_item   item;
-   struct upd_usage_entry   *entry;
-   struct upd_sensor*sensor;
int   size;
int   i;
void *desc;
@@ -164,6 +172,7 @@ upd_attach(struct device *parent, struct
sc-sc_hdev.sc_parent = uha-parent;
sc-sc_reports = NULL;
sc-sc_sensors = NULL;
+   SLIST_INIT(sc-sc_root_sensors);
 
strlcpy(sc-sc_sensordev.xname, DEVNAME(sc),
sizeof(sc-sc_sensordev.xname));
@@ -174,13 +183,41 @@ upd_attach(struct device *parent, struct
 
sc-sc_reports = mallocarray(sc-sc_max_repid,
sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO);
-   sc-sc_sensors = mallocarray(nitems(upd_usage_table),
+   sc-sc_sensors = mallocarray(UPD_MAX_SENSORS,
sizeof(struct upd_sensor), M_USBDEV, M_WAITOK | M_ZERO);
-   

upd(4) report order - patch 6/7

2015-04-24 Thread David Higgs
This is the big change that puts all the previous work together.

When a sensor update is needed, mark its report as pending; do this in 
dependency order.  When a report fails to query/reply, mark it and its children 
as invalid.  When the BatteryPresent says there is no battery, mark its 
children as invalid too.

If BatteryPresent is on a repid that comes numerically after a child, the 
do/while loop will try again until there are no more pending reports.

If BatteryPresent is on the same repid as a child, the report-sensors list 
will have already put it in the correct order so the parent will update before 
the child.

If BatteryPresent=false invalidates children that belong to an already-pending 
report, they will not be updated, because sensor-pending will no longer be set.

--david

--- a/upd.c
+++ b/upd.c
@@ -81,6 +81,7 @@ static struct upd_usage_entry upd_usage_
 struct upd_report {
size_t  size;
SLIST_HEAD(, upd_sensor)sensors;
+   int pending;
 };
 
 SLIST_HEAD(upd_sensor_head, upd_sensor);
@@ -91,6 +92,7 @@ struct upd_sensor {
struct upd_sensor_head  children;
SLIST_ENTRY(upd_sensor) dep_next;
SLIST_ENTRY(upd_sensor) rep_next;
+   int pending;
 };
 
 struct upd_softc {
@@ -113,7 +115,9 @@ void upd_attach_sensor_tree(struct upd_s
 int  upd_detach(struct device *, int);
 
 void upd_refresh(void *);
-void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
+void upd_request_children(struct upd_softc *, struct upd_sensor_head *, int);
+void upd_update_report_cb(void *, int, void *, int);
+void upd_update_sensor(struct upd_softc *, struct upd_sensor *, uint8_t *, 
int);
 void upd_update_sensor_value(struct upd_softc *, struct upd_sensor *,
 uint8_t *, int);
 void upd_intr(struct uhidev *, void *, uint);
@@ -285,30 +289,59 @@ upd_detach(struct device *self, int flag
 void
 upd_refresh(void *arg)
 {
-   struct upd_softc*sc = (struct upd_softc *)arg;
+   struct upd_softc*sc = arg;
struct upd_report   *report;
uint8_t buf[256];
-   int repid, actlen;
+   int repid, actlen, done;
 
-   for (repid = 0; repid  sc-sc_max_repid; repid++) {
-   report = sc-sc_reports[repid];
-   if (SLIST_EMPTY(report-sensors))
-   continue;
+   /* request root sensors */
+   upd_request_children(sc, sc-sc_root_sensors, 1);
 
-   memset(buf, 0x0, sizeof(buf));
-   actlen = uhidev_get_report(sc-sc_hdev.sc_parent,
-   UHID_FEATURE_REPORT, repid, buf, report-size);
-
-   if (actlen == -1) {
-   DPRINTF((upd: failed to get report id=%02x\n, repid));
-   continue;
+   /* repeat until all reports queried */
+   do {
+   done = 1;
+   for (repid = 0; repid  sc-sc_max_repid; repid++) {
+   report = sc-sc_reports[repid];
+   if (!report-pending)
+   continue;
+   memset(buf, 0x0, sizeof(buf));
+   actlen = uhidev_get_report(sc-sc_hdev.sc_parent,
+   UHID_FEATURE_REPORT, repid, buf, report-size);
+   upd_update_report_cb(sc, repid, buf, actlen);
+   done = 0;
}
+   } while (!done);
+}
+
+void
+upd_request_children(struct upd_softc *sc, struct upd_sensor_head *queue,
+int valid)
+{
+   struct upd_sensor   *sensor;
+   struct upd_report   *report;
+   int  repid;
 
-   /* Deal with buggy firmwares. */
-   if (actlen  report-size)
-   report-size = actlen;
+   SLIST_FOREACH(sensor, queue, dep_next) {
+   repid = sensor-hitem.report_ID;
+   report = sc-sc_reports[repid];
 
-   upd_update_sensors(sc, buf, report-size, repid);
+   if (sensor-pending)
+   DPRINTF((%s: %s still pending (repid=%d)\n,
+   DEVNAME(sc), sensor-ksensor.desc, repid));
+   else if (!valid) {
+   DPRINTF((%s: marking %s invalid\n,
+   DEVNAME(sc), sensor-ksensor.desc));
+   sensor-pending = 1;
+   upd_update_sensor(sc, sensor, NULL, -1);
+   } else if (report-pending)
+   /* already requested */
+   sensor-pending = 1;
+   else {
+   DPRINTF((%s: %s requests repid %d\n,
+   DEVNAME(sc), sensor-ksensor.desc, repid));
+   sensor-pending = 1;
+   report-pending = 1;
+   }
}
 }
 

upd(4) with async reports

2015-04-07 Thread David Higgs
Features of this diff:
- All upd(4) reports are queried asynchronously
- Use pending status to prevent duplicate usb queries
- No apparent changes from end-user point of view

Note: depends on the previous upd(4) LIST diff, not yet committed.

As usual, feedback and comments are welcome.

--david

--- a/upd.c
+++ b/upd.c
@@ -73,17 +73,20 @@ static struct upd_usage_entry upd_usage_
 struct upd_report {
size_t  size;
int enabled;
+   int pending;
 };
 
 struct upd_sensor {
struct ksensor  ksensor;
struct hid_item hitem;
LIST_ENTRY(upd_sensor)  next;
+   int pending;
 };
 
 struct upd_softc {
struct uhidevsc_hdev;
u_intsc_max_repid;
+   char sc_buf[256];
 
/* sensor framework */
struct ksensordevsc_sensordev;
@@ -98,7 +101,9 @@ void upd_attach(struct device *, struct
 int  upd_detach(struct device *, int);
 
 void upd_refresh(void *);
-void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
+void upd_request_sensor_refresh(struct upd_softc *, struct upd_sensor *);
+void upd_update_report_cb(void *, int, void *, int);
+void upd_update_sensor(struct upd_softc *, struct upd_sensor *, uint8_t *, 
int);
 void upd_intr(struct uhidev *, void *, uint);
 struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
@@ -258,30 +263,68 @@ void
 upd_refresh(void *arg)
 {
struct upd_softc*sc = (struct upd_softc *)arg;
-   struct upd_report   *report;
-   uint8_t buf[256];
-   int repid, actlen;
+   struct upd_sensor   *sensor;
 
-   for (repid = 0; repid  sc-sc_max_repid; repid++) {
-   report = sc-sc_reports[repid];
-   if (!report-enabled)
-   continue;
+   LIST_FOREACH(sensor, sc-sc_sensorlist, next)
+   upd_request_sensor_refresh(sc, sensor);
+}
 
-   memset(buf, 0x0, sizeof(buf));
-   actlen = uhidev_get_report(sc-sc_hdev.sc_parent,
-   UHID_FEATURE_REPORT, repid, buf, report-size);
+void
+upd_request_sensor_refresh(struct upd_softc *sc, struct upd_sensor *sensor)
+{
+   struct upd_report   *report;
+   int repid;
 
-   if (actlen == -1) {
-   DPRINTF((upd: failed to get report id=%02x\n, repid));
-   continue;
-   }
+   repid = sensor-hitem.report_ID;
+   report = sc-sc_reports[repid];
+   if (sensor-pending)
+   DPRINTF((%s: sensor %s (repid=%d) still pending\n,
+   sc-sc_sensordev.xname, sensor-ksensor.desc, repid));
+   else if (report-pending)
+   /* already requested */
+   sensor-pending = 1;
+   else if (uhidev_get_report_async(sc-sc_hdev.sc_parent,
+   UHID_FEATURE_REPORT, repid, sc-sc_buf, report-size,
+   sc, upd_update_report_cb)  0) {
+   DPRINTF((%s: %s requests repid %d\n,
+   sc-sc_sensordev.xname, sensor-ksensor.desc, repid));
+   report-pending = 1;
+   sensor-pending = 1;
+   } else {
+   DPRINTF((%s: failed to request %s (repid=%d)\n,
+   sc-sc_sensordev.xname, sensor-ksensor.desc, repid));
+   sensor-ksensor.status = SENSOR_S_UNKNOWN;
+   sensor-ksensor.flags |= SENSOR_FINVALID;
+   }
+}
 
-   /* Deal with buggy firmwares. */
-   if (actlen  report-size)
-   report-size = actlen;
+void
+upd_update_report_cb(void *priv, int repid, void *data, int len)
+{
+   struct upd_softc*sc = priv;
+   struct upd_report   *report;
+   struct upd_sensor   *sensor;
 
-   upd_update_sensors(sc, buf, report-size, repid);
+   /* handle buggy firmware */
+   report = sc-sc_reports[repid];
+   if (len  0  report-size != len) {
+   DPRINTF((%s: adjusting size of repid %d\n,
+   sc-sc_sensordev.xname, repid));
+   report-size = len;
}
+
+   LIST_FOREACH(sensor, sc-sc_sensorlist, next) {
+   if (sensor-hitem.report_ID == repid) {
+   if (len  0)
+   upd_update_sensor(sc, sensor, data, len);
+   else {
+   sensor-ksensor.status = SENSOR_S_UNKNOWN;
+   sensor-ksensor.flags |= SENSOR_FINVALID;
+   }
+   sensor-pending = 0;
+   }
+   }
+   report-pending = 0;
 }
 
 struct upd_usage_entry *
@@ -313,32 +356,22 @@ upd_lookup_sensor(struct upd_softc *sc,
 }
 
 void
-upd_update_sensors(struct upd_softc *sc, uint8_t 

Re: Use LIST for upd(4) sensors

2015-04-01 Thread David Higgs
On Wed, Apr 1, 2015 at 7:52 AM, Martin Pieuchot m...@openbsd.org wrote:

 On 31/03/15(Tue) 23:06, David Higgs wrote:
  This was much more straightforward than expected.
 
  - Replace an array with a LIST of allocated sensors.
  - Remove or rescope variables counting sensors.
  - Allocated sensors are always attached.
  - Drop an unnecessary size calculation.

 Do you need this for an upcoming change?  I fail to see the benefit to
 have a malloc(9) call per item, afaik theses items are really small and
 you have at most 10 of them...

 No, I just extrapolated too much from your suggestion to put attached
sensors on a LIST.  I'll adjust and resubmit.

Thanks.

--david


Use LIST for upd(4) sensors

2015-03-31 Thread David Higgs
This was much more straightforward than expected.

- Replace an array with a LIST of allocated sensors.
- Remove or rescope variables counting sensors.
- Allocated sensors are always attached.
- Drop an unnecessary size calculation.

Thanks.

--david

--- a/upd.c
+++ b/upd.c
@@ -23,6 +23,7 @@
 #include sys/kernel.h
 #include sys/malloc.h
 #include sys/device.h
+#include sys/queue.h
 #include sys/sensors.h
 
 #include dev/usb/hid.h
@@ -77,20 +78,18 @@ struct upd_report {
 struct upd_sensor {
struct ksensor  ksensor;
struct hid_item hitem;
-   int attached;
+   LIST_ENTRY(upd_sensor)  next;
 };
 
 struct upd_softc {
struct uhidevsc_hdev;
-   int  sc_num_sensors;
u_intsc_max_repid;
-   u_intsc_max_sensors;
 
/* sensor framework */
struct ksensordevsc_sensordev;
struct sensor_task  *sc_sensortask;
struct upd_report   *sc_reports;
-   struct upd_sensor   *sc_sensors;
+   LIST_HEAD(, upd_sensor)  sc_sensors;
 };
 
 int  upd_match(struct device *, void *, void *);
@@ -155,14 +154,14 @@ upd_attach(struct device *parent, struct
struct hid_data  *hdata;
struct upd_usage_entry   *entry;
struct upd_sensor*sensor;
+   int   num_sensors;
int   size;
void *desc;
 
sc-sc_hdev.sc_intr = upd_intr;
sc-sc_hdev.sc_parent = uha-parent;
sc-sc_reports = NULL;
-   sc-sc_sensors = NULL;
-   sc-sc_max_sensors = nitems(upd_usage_table);
+   LIST_INIT(sc-sc_sensors);
 
strlcpy(sc-sc_sensordev.xname, sc-sc_hdev.sc_dev.dv_xname,
sizeof(sc-sc_sensordev.xname));
@@ -173,14 +172,11 @@ upd_attach(struct device *parent, struct
 
sc-sc_reports = mallocarray(sc-sc_max_repid,
sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO);
-   sc-sc_sensors = mallocarray(sc-sc_max_sensors,
-   sizeof(struct upd_sensor), M_USBDEV, M_WAITOK | M_ZERO);
-   size = sc-sc_max_sensors * sizeof(struct upd_sensor);
-   sc-sc_num_sensors = 0;
+   num_sensors = 0;
uhidev_get_report_desc(uha-parent, desc, size);
for (hdata = hid_start_parse(desc, size, hid_feature);
 hid_get_item(hdata, item) 
-sc-sc_num_sensors  sc-sc_max_sensors; ) {
+num_sensors  nitems(upd_usage_table); ) {
DPRINTF((upd: repid=%d\n, item.report_ID));
if (item.kind != hid_feature ||
item.report_ID  0 ||
@@ -196,7 +192,8 @@ upd_attach(struct device *parent, struct
if (sensor != NULL)
continue;
 
-   sensor = sc-sc_sensors[sc-sc_num_sensors];
+   sensor = malloc(sizeof(struct upd_sensor), M_USBDEV,
+   M_WAITOK | M_ZERO);
memcpy(sensor-hitem, item, sizeof(struct hid_item));
strlcpy(sensor-ksensor.desc, entry-usage_name,
sizeof(sensor-ksensor.desc));
@@ -205,8 +202,8 @@ upd_attach(struct device *parent, struct
sensor-ksensor.status = SENSOR_S_UNKNOWN;
sensor-ksensor.value = 0;
sensor_attach(sc-sc_sensordev, sensor-ksensor);
-   sensor-attached = 1;
-   sc-sc_num_sensors++;
+   LIST_INSERT_HEAD(sc-sc_sensors, sensor, next);
+   num_sensors++;
 
if (sc-sc_reports[item.report_ID].enabled)
continue;
@@ -216,7 +213,7 @@ upd_attach(struct device *parent, struct
sc-sc_reports[item.report_ID].enabled = 1;
}
hid_end_parse(hdata);
-   DPRINTF((upd: sc_num_sensors=%d\n, sc-sc_num_sensors));
+   DPRINTF((upd: num_sensors=%d\n, num_sensors));
 
sc-sc_sensortask = sensor_task_register(sc, upd_refresh, 6);
if (sc-sc_sensortask == NULL) {
@@ -235,7 +232,7 @@ upd_detach(struct device *self, int flag
 {
struct upd_softc*sc = (struct upd_softc *)self;
struct upd_sensor   *sensor;
-   int  i;
+   struct upd_sensor   *t;
 
if (sc-sc_sensortask != NULL) {
wakeup(sc-sc_sensortask);
@@ -244,15 +241,14 @@ upd_detach(struct device *self, int flag
 
sensordev_deinstall(sc-sc_sensordev);
 
-   for (i = 0; i  sc-sc_num_sensors; i++) {
-   sensor = sc-sc_sensors[i];
-   if (sensor-attached)
-   sensor_detach(sc-sc_sensordev, sensor-ksensor);
+   LIST_FOREACH_SAFE(sensor, sc-sc_sensors, next, t) {
+   sensor_detach(sc-sc_sensordev, sensor-ksensor);
DPRINTF((upd_detach: %s\n, sensor-ksensor.desc));
+   LIST_REMOVE(sensor, next);
+   free(sensor, M_USBDEV, sizeof(struct upd_sensor));
  

Simplify upd(4) attach

2015-03-31 Thread David Higgs
First in what will probably be a slow trickle, as I split my original big diff 
into more-easily reviewed chunks and test each in sequence.

This patch makes upd_attach less confusing:
1. Ignore all bogus report IDs up front, they shouldn't be queried.
2. When a sensor is attached, it will be found by upd_lookup_sensor, so don’t 
check attached.

Thanks.

--david

--- a/upd.c
+++ b/upd.c
@@ -183,7 +183,8 @@ upd_attach(struct device *parent, struct
 sc-sc_num_sensors  sc-sc_max_sensors; ) {
DPRINTF((upd: repid=%d\n, item.report_ID));
if (item.kind != hid_feature ||
-   item.report_ID  0)
+   item.report_ID  0 ||
+   item.report_ID = sc-sc_max_repid)
continue;
 
if ((entry = upd_lookup_usage_entry(item)) == NULL)
@@ -192,11 +193,10 @@ upd_attach(struct device *parent, struct
/* filter repeated usages, avoid duplicated sensors */
sensor = upd_lookup_sensor(sc, entry-usage_pg,
entry-usage_id);
-   if (sensor  sensor-attached)
+   if (sensor != NULL)
continue;
 
sensor = sc-sc_sensors[sc-sc_num_sensors];
-   /* keep our copy of hid_item */
memcpy(sensor-hitem, item, sizeof(struct hid_item));
strlcpy(sensor-ksensor.desc, entry-usage_name,
sizeof(sensor-ksensor.desc));
@@ -208,8 +208,7 @@ upd_attach(struct device *parent, struct
sensor-attached = 1;
sc-sc_num_sensors++;
 
-   if (item.report_ID = sc-sc_max_repid ||
-   sc-sc_reports[item.report_ID].enabled)
+   if (sc-sc_reports[item.report_ID].enabled)
continue;
 
sc-sc_reports[item.report_ID].size = hid_report_size(desc,




Re: Async upd(4)

2015-03-09 Thread David Higgs
On Mon, Mar 9, 2015 at 6:04 AM, Martin Pieuchot mpieuc...@nolizard.org
wrote:

 On 05/03/15(Thu) 12:25, David Higgs wrote:
 
  On Mar 3, 2015, at 8:44 AM, David Higgs hig...@gmail.com wrote:
 
   With much help from mpi@, I have made a first big step towards
 improving upd(4).  I'm not sure when tree lock ends, but I'm still happy to
 accept feedback if right now isn't the time to commit.  There's plenty more
 to do, but I'd like to get this ironed out before moving on.
  
   New behavior with this diff:
   - Leverage new USB async reporting (must have up-to-date tree)
   - Sensor dependencies ensure reports are gathered in useful order
   - Track pending reports to minimize USB queries
   - Relevant sensors immediately invalidated when battery is removed
 (instead of waiting for the next refresh)
  
   Things that may need sanity checks:
   - Simplified upd_attach; the old code seemed to have redundant /
 confusing logic
   - Integer promotion/truncation with batpres and hdata/adjust variables
 
  Below is an overhauled diff with some additional considerations I came
 up with.
 
  Improvements on the previous version:
  - ACPresent no longer depends on BatteryPresent
  - Sensor dependencies now handled manually, so dynamic behavior can be
 added later.
  - Avoid hypothetical cases where certain USB report layouts could
 trigger:
- Infinite loops in sensor dependencies.
- Updating sensor contents using stale information.
- Unnecessary sensor invalidation.
- Redundant USB transfers.
 
  As before, comments, questions, and feedback are welcome.

 That's great, some comments inline.

   int  upd_match(struct device *, void *, void *);
   void upd_attach(struct device *, struct device *, void *);
   int  upd_detach(struct device *, int);
 
   void upd_refresh(void *);
  -void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int,
 int);
  -void upd_intr(struct uhidev *, void *, uint);
  +void upd_request_sensor_refresh(struct upd_softc *, uint8_t, uint8_t,
 int);
  +void upd_update_sensor_cb(void *, int, void *, int);
  +void upd_mark_sensor_invalid(struct upd_softc *, struct upd_sensor *,
 int);
   struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
   struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
  +int upd_battery_present(struct upd_softc *);
  +void upd_update_batpres_sensor(struct upd_softc *, struct upd_sensor *,
  +uint8_t *, int);
  +void upd_update_batdep_sensor(struct upd_softc *, struct upd_sensor *,
  +uint8_t *, int);
  +void upd_update_sensor_value(struct upd_softc *, struct upd_sensor *,
  +uint8_t *, int);
  +void upd_intr(struct uhidev *, void *, uint);
  +
  +static struct upd_usage_entry upd_usage_table[] = {
  + { HUP_BATTERY,  HUB_REL_STATEOF_CHARGE,
  + SENSOR_PERCENT, RelativeStateOfCharge,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_ABS_STATEOF_CHARGE,
  + SENSOR_PERCENT, AbsoluteStateOfCharge,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_REM_CAPACITY,
  + SENSOR_PERCENT, RemainingCapacity,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_FULLCHARGE_CAPACITY,
  + SENSOR_PERCENT, FullChargeCapacity,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_CHARGING,
  + SENSOR_INDICATOR,   Charging,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_DISCHARGING,
  + SENSOR_INDICATOR,   Discharging,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_BATTERY_PRESENT,
  + SENSOR_INDICATOR,   BatteryPresent,
  + upd_update_batpres_sensor },
  + { HUP_POWER,HUP_SHUTDOWN_IMMINENT,
  + SENSOR_INDICATOR,   ShutdownImminent,
  + upd_update_sensor_value },
  + { HUP_BATTERY,  HUB_AC_PRESENT,
  + SENSOR_INDICATOR,   ACPresent,
  + upd_update_batdep_sensor },
  + { HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
  + SENSOR_TIMEDELTA,   AtRateTimeToFull,
  + upd_update_batdep_sensor }
  +};

 I see that all the HUP_BATTERY sensors have the same dependency.   Why
 not have a table for items without dependency (the parents) and a child
 table per parent?  This way you would have only one upd_update_sensor
 function.  This is really the key of this driver.  Why a flat list like
 you have right now you need much more code, flags and customs functions.


This does seem simpler; I'll give it a shot.


 
   struct cfdriver upd_cd = {
NULL, upd, DV_DULL
  @@ -183,38 +207,30 @@ upd_attach(struct device *parent, struct
 sc-sc_num_sensors  sc-sc_max_sensors; ) {
DPRINTF((upd: repid=%d\n, item.report_ID));
if (item.kind != hid_feature ||
  - item.report_ID  0)
  + item.report_ID  0 ||
  + item.report_ID = sc-sc_max_repid)
continue;
  -
if ((entry

Re: Async upd(4)

2015-03-05 Thread David Higgs

On Mar 3, 2015, at 8:44 AM, David Higgs hig...@gmail.com wrote:

 With much help from mpi@, I have made a first big step towards improving 
 upd(4).  I’m not sure when tree lock ends, but I’m still happy to accept 
 feedback if right now isn’t the time to commit.  There’s plenty more to do, 
 but I’d like to get this ironed out before moving on.
 
 New behavior with this diff:
 - Leverage new USB async reporting (must have up-to-date tree)
 - Sensor dependencies ensure reports are gathered in useful order
 - Track pending reports to minimize USB queries
 - Relevant sensors immediately invalidated when battery is removed (instead 
 of waiting for the next refresh)
 
 Things that may need sanity checks:
 - Simplified upd_attach; the old code seemed to have redundant / confusing 
 logic
 - Integer promotion/truncation with batpres and hdata/adjust variables

Below is an overhauled diff with some additional considerations I came up with.

Improvements on the previous version:
- ACPresent no longer depends on BatteryPresent
- Sensor dependencies now handled manually, so dynamic behavior can be added 
later.
- Avoid hypothetical cases where certain USB report layouts could trigger:
  - Infinite loops in sensor dependencies.
  - Updating sensor contents using stale information.
  - Unnecessary sensor invalidation.
  - Redundant USB transfers.

As before, comments, questions, and feedback are welcome.

--david


Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.13
diff -u -p -r1.13 upd.c
--- upd.c   11 Jan 2015 03:08:38 -  1.13
+++ upd.c   5 Mar 2015 17:06:19 -
@@ -39,45 +39,17 @@
 #define DPRINTF(x)
 #endif
 
-struct upd_usage_entry {
-   uint8_t usage_pg;
-   uint8_t usage_id;
-   enum sensor_typesenstype;
-   char*usage_name; /* sensor string */
-};
-
-static struct upd_usage_entry upd_usage_table[] = {
-   { HUP_BATTERY,  HUB_REL_STATEOF_CHARGE,
-   SENSOR_PERCENT,  RelativeStateOfCharge },
-   { HUP_BATTERY,  HUB_ABS_STATEOF_CHARGE,
-   SENSOR_PERCENT,  AbsoluteStateOfCharge },
-   { HUP_BATTERY,  HUB_REM_CAPACITY,
-   SENSOR_PERCENT,  RemainingCapacity },
-   { HUP_BATTERY,  HUB_FULLCHARGE_CAPACITY,
-   SENSOR_PERCENT,  FullChargeCapacity },
-   { HUP_BATTERY,  HUB_CHARGING,
-   SENSOR_INDICATOR,Charging },
-   { HUP_BATTERY,  HUB_DISCHARGING,
-   SENSOR_INDICATOR,Discharging },
-   { HUP_BATTERY,  HUB_BATTERY_PRESENT,
-   SENSOR_INDICATOR,BatteryPresent },
-   { HUP_POWER,HUP_SHUTDOWN_IMMINENT,
-   SENSOR_INDICATOR,ShutdownImminent },
-   { HUP_BATTERY,  HUB_AC_PRESENT,
-   SENSOR_INDICATOR,ACPresent },
-   { HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
-   SENSOR_TIMEDELTA,AtRateTimeToFull }
-};
-
 struct upd_report {
size_t  size;
-   int enabled;
+   int pending;
 };
 
 struct upd_sensor {
struct ksensor  ksensor;
struct hid_item hitem;
+   struct upd_usage_entry  *entry;
int attached;
+   int pending;
 };
 
 struct upd_softc {
@@ -85,6 +57,7 @@ struct upd_softc {
int  sc_num_sensors;
u_intsc_max_repid;
u_intsc_max_sensors;
+   char sc_buf[256];
 
/* sensor framework */
struct ksensordevsc_sensordev;
@@ -93,15 +66,66 @@ struct upd_softc {
struct upd_sensor   *sc_sensors;
 };
 
+struct upd_usage_entry {
+   uint8_t usage_pg;
+   uint8_t usage_id;
+   enum sensor_typesenstype;
+   char*usage_name; /* sensor string */
+   void (*update_sensor)(struct upd_softc *, struct upd_sensor *,
+   uint8_t *, int);
+};
+
 int  upd_match(struct device *, void *, void *);
 void upd_attach(struct device *, struct device *, void *);
 int  upd_detach(struct device *, int);
 
 void upd_refresh(void *);
-void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
-void upd_intr(struct uhidev *, void *, uint);
+void upd_request_sensor_refresh(struct upd_softc *, uint8_t, uint8_t, int);
+void upd_update_sensor_cb(void *, int, void *, int);
+void upd_mark_sensor_invalid(struct upd_softc *, struct upd_sensor *, int);
 struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
+int upd_battery_present(struct upd_softc *);
+void upd_update_batpres_sensor(struct upd_softc *, struct upd_sensor *,
+uint8_t *, int);
+void upd_update_batdep_sensor(struct upd_softc *, struct upd_sensor *,
+uint8_t *, int);
+void

Async upd(4)

2015-03-03 Thread David Higgs
With much help from mpi@, I have made a first big step towards improving 
upd(4).  I’m not sure when tree lock ends, but I’m still happy to accept 
feedback if right now isn’t the time to commit.  There’s plenty more to do, but 
I’d like to get this ironed out before moving on.

New behavior with this diff:
- Leverage new USB async reporting (must have up-to-date tree)
- Sensor dependencies ensure reports are gathered in useful order
- Track pending reports to minimize USB queries
- Relevant sensors immediately invalidated when battery is removed (instead of 
waiting for the next refresh)

Things that may need sanity checks:
- Simplified upd_attach; the old code seemed to have redundant / confusing logic
- Integer promotion/truncation with batpres and hdata/adjust variables

Suggestions, bug reports, and feedback welcome.

--david

Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.13
diff -u -p -r1.13 upd.c
--- upd.c   11 Jan 2015 03:08:38 -  1.13
+++ upd.c   20 Feb 2015 02:28:04 -
@@ -39,44 +39,15 @@
 #define DPRINTF(x)
 #endif
 
-struct upd_usage_entry {
-   uint8_t usage_pg;
-   uint8_t usage_id;
-   enum sensor_typesenstype;
-   char*usage_name; /* sensor string */
-};
-
-static struct upd_usage_entry upd_usage_table[] = {
-   { HUP_BATTERY,  HUB_REL_STATEOF_CHARGE,
-   SENSOR_PERCENT,  RelativeStateOfCharge },
-   { HUP_BATTERY,  HUB_ABS_STATEOF_CHARGE,
-   SENSOR_PERCENT,  AbsoluteStateOfCharge },
-   { HUP_BATTERY,  HUB_REM_CAPACITY,
-   SENSOR_PERCENT,  RemainingCapacity },
-   { HUP_BATTERY,  HUB_FULLCHARGE_CAPACITY,
-   SENSOR_PERCENT,  FullChargeCapacity },
-   { HUP_BATTERY,  HUB_CHARGING,
-   SENSOR_INDICATOR,Charging },
-   { HUP_BATTERY,  HUB_DISCHARGING,
-   SENSOR_INDICATOR,Discharging },
-   { HUP_BATTERY,  HUB_BATTERY_PRESENT,
-   SENSOR_INDICATOR,BatteryPresent },
-   { HUP_POWER,HUP_SHUTDOWN_IMMINENT,
-   SENSOR_INDICATOR,ShutdownImminent },
-   { HUP_BATTERY,  HUB_AC_PRESENT,
-   SENSOR_INDICATOR,ACPresent },
-   { HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
-   SENSOR_TIMEDELTA,AtRateTimeToFull }
-};
-
 struct upd_report {
size_t  size;
-   int enabled;
+   int pending;
 };
 
 struct upd_sensor {
struct ksensor  ksensor;
struct hid_item hitem;
+   struct upd_usage_entry  *entry;
int attached;
 };
 
@@ -85,6 +56,7 @@ struct upd_softc {
int  sc_num_sensors;
u_intsc_max_repid;
u_intsc_max_sensors;
+   char sc_buf[256];
 
/* sensor framework */
struct ksensordevsc_sensordev;
@@ -93,6 +65,17 @@ struct upd_softc {
struct upd_sensor   *sc_sensors;
 };
 
+struct upd_usage_entry {
+   uint8_t usage_pg;
+   uint8_t usage_id;
+   uint8_t parent_pg;
+   uint8_t parent_id;
+   enum sensor_typesenstype;
+   char*usage_name; /* sensor string */
+   void (*update_sensor)(struct upd_softc *, struct upd_sensor *,
+   uint8_t *, int);
+};
+
 int  upd_match(struct device *, void *, void *);
 void upd_attach(struct device *, struct device *, void *);
 int  upd_detach(struct device *, int);
@@ -100,8 +83,58 @@ int  upd_detach(struct device *, int);
 void upd_refresh(void *);
 void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
 void upd_intr(struct uhidev *, void *, uint);
+void upd_refresh_sensor_tree(struct upd_softc *, uint8_t, uint8_t, int);
+void upd_get_report_async_cb(void *, int, void *, int);
 struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
+void upd_update_batdep_sensor(struct upd_softc *, struct upd_sensor *,
+uint8_t *, int);
+void upd_update_sensor_value(struct upd_softc *, struct upd_sensor *,
+uint8_t *, int);
+
+/* dependency order only for developer sanity */
+static struct upd_usage_entry upd_usage_table[] = {
+   { HUP_POWER,HUP_SHUTDOWN_IMMINENT,
+   HUP_UNDEFINED,  0,
+   SENSOR_INDICATOR,   ShutdownImminent,
+   upd_update_sensor_value },
+   { HUP_BATTERY,  HUB_BATTERY_PRESENT,
+   HUP_UNDEFINED,  0,
+   SENSOR_INDICATOR,   BatteryPresent,
+   upd_update_sensor_value },
+   { HUP_BATTERY,  HUB_AC_PRESENT,
+   HUP_UNDEFINED,  0,
+   SENSOR_INDICATOR,   ACPresent,
+   upd_update_sensor_value },
+   { HUP_BATTERY, 

Re: USBD_NO_COPY problems

2015-02-19 Thread David Higgs
On Feb 13, 2015, at 7:29 AM, David Higgs hig...@gmail.com wrote:
 On Friday, February 13, 2015, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 13/02/15(Fri) 00:28, David Higgs wrote:
  I guess nobody else has tried calling uhidev_get_report_async() yet.  :)
 
  First I was getting a NULL pointer deref in the uhidev async callback.
  Then I realized that due to USBD_NO_COPY, xfer-buffer was always
  NULL.  Next, I tried to use the DMA buffer, but I ended up in DDB in a
  very cryptic way.  I believe this is because the DMA buffer isn't
  available when the callback is invoked.
 
  For the async callback to get a valid dmabuf, it needs to be invoked
  prior to usb_freemem() in usbd_transfer_complete().  The xfer-status
  determination would need to move up too.  I'd do this myself but I
  don't understand the logic and ordering of pipe-repeat stuff, and am
  concerned about unintentionally breaking other devices.
 
  This is partially my fault, because I tested the original diff that
  added the USBD_NO_COPY semantics to verify that it didn't break my
  synchronous code paths, but hadn't yet written anything for upd(4) to
  check the async ones.
 
 Does the diff below help? 
 
 Partially but not enough.  I had already figured out that I needed that to 
 solve the NULL pointer dereference.  See my 2nd paragraph above.
 
OK, I figured out my issue - the crazy DDB backtrace is produced when you 
execute a NULL callback.

It still doesn’t seem legal for the callback to access DMA buffer contents 
after they are “freed”.  I assume this won’t work in all cases (host 
controllers / architectures / cache behaviors), but I don’t experience any 
problems in my i386 VM.  I tried reordering parts of usbd_transfer_complete(), 
but DIAGNOSTIC code became very unhappy with the results.

Fortunately, the diff below doesn’t touch that code path and just fixes the 
uhidev layer.  My async upd(4) changes will be forthcoming in a different 
thread.

Thanks.

--david

Index: uhidev.c
===
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.69
diff -u -p -r1.69 uhidev.c
--- uhidev.c22 Jan 2015 10:27:47 -  1.69
+++ uhidev.c20 Feb 2015 02:27:29 -
@@ -53,6 +53,7 @@
 #include dev/usb/usbdi.h
 #include dev/usb/usbdi_util.h
 #include dev/usb/usbdivar.h
+#include dev/usb/usb_mem.h
 #include dev/usb/hid.h
 #include dev/usb/usb_quirks.h
 
@@ -747,15 +748,17 @@ void
 uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
 {
struct uhidev_async_info *info = priv;
+   char *buf;
int len = -1;
 
if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
len = xfer-actlen;
+   buf = KERNADDR(xfer-dmabuf, 0);
if (info-id  0) {
len--;
-   memcpy(info-data, xfer-buffer + 1, len);
+   memcpy(info-data, buf + 1, len);
} else {
-   memcpy(info-data, xfer-buffer, len);
+   memcpy(info-data, buf, len);
}
}
info-callback(info-priv, info-id, info-data, len);
@@ -803,7 +806,7 @@ uhidev_get_report_async(struct uhidev_so
USETW(req.wIndex, sc-sc_ifaceno);
USETW(req.wLength, len);
 
-   if (usbd_request_async(xfer, req, priv, uhidev_get_report_async_cb)) {
+   if (usbd_request_async(xfer, req, info, uhidev_get_report_async_cb)) {
free(info, M_TEMP, sizeof(*info));
actlen = -1;
}




Re: USBD_NO_COPY problems

2015-02-14 Thread David Higgs

On Feb 13, 2015, at 7:29 AM, David Higgs hig...@gmail.com wrote:

 On Friday, February 13, 2015, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 13/02/15(Fri) 00:28, David Higgs wrote:
  I guess nobody else has tried calling uhidev_get_report_async() yet.  :)
 
  First I was getting a NULL pointer deref in the uhidev async callback.
  Then I realized that due to USBD_NO_COPY, xfer-buffer was always
  NULL.  Next, I tried to use the DMA buffer, but I ended up in DDB in a
  very cryptic way.  I believe this is because the DMA buffer isn't
  available when the callback is invoked.
 
  For the async callback to get a valid dmabuf, it needs to be invoked
  prior to usb_freemem() in usbd_transfer_complete().  The xfer-status
  determination would need to move up too.  I'd do this myself but I
  don't understand the logic and ordering of pipe-repeat stuff, and am
  concerned about unintentionally breaking other devices.
 
  This is partially my fault, because I tested the original diff that
  added the USBD_NO_COPY semantics to verify that it didn't break my
  synchronous code paths, but hadn't yet written anything for upd(4) to
  check the async ones.
 
 Does the diff below help? 
 
 Partially but not enough.  I had already figured out that I needed that to 
 solve the NULL pointer dereference.  See my 2nd paragraph above.

Below is the diff I’m currently running with, seeing the same problems.  This 
may actually be indicative of some error in my big upd(4) update - which I 
didn’t include - but I’m not sure how to find out for sure because I’m not sure 
how to interpret the DDB trace (hand-copied, may have errors). There were two 
async requests pending when I got kicked into the debugger.  Any help or 
suggestions would be very welcome at this point.

Thanks.

--david

uvm_fault(0xd565f480, 0x0, 0, 1) - e
kernel: page fault trap, code = 0
Stopped at   0:uvm_fault(0xd565f480, 0x0, 0, 1) - e
kernel: page fault trap, code = 0
Stopped at   db_read_bytes+0x17:movzbl   0(%esi,%ecx,1),%eax
ddb trace
db_read_bytes(0,1,f375ea44,0,f375ea54) at db_read_bytes+0x17
db_get_value(0,1,0,0,d09e1ada) at db_get_value+0x38
db_disasm(0,0,d03cc470,d03cc495,d09b6b38,f375eb14,0,0,f375eb14) at 
db_disasm+0x31
db_print_loc_and_inst(0,f375,eb2c,f375eb38,d03cc495,d09e1acb) at 
db_print_loc_and_inst+0x3e
db_trap(6,0,58,0,f375eb74) at db_trap+0x89
kdb_trap(6,0,f375ebe4,1,e) at kdb_trap+0xcc
trap() at trap+0x2e5
— trap (number 0) —
Bad frame pointer: 0xd56641e0
0:
ddb

Index: uhidev.c
===
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.69
diff -u -p -r1.69 uhidev.c
--- uhidev.c22 Jan 2015 10:27:47 -  1.69
+++ uhidev.c14 Feb 2015 15:18:47 -
@@ -53,6 +53,7 @@
 #include dev/usb/usbdi.h
 #include dev/usb/usbdi_util.h
 #include dev/usb/usbdivar.h
+#include dev/usb/usb_mem.h
 #include dev/usb/hid.h
 #include dev/usb/usb_quirks.h
 
@@ -747,15 +748,17 @@ void
 uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
 {
struct uhidev_async_info *info = priv;
+   char *buf;
int len = -1;
 
if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
len = xfer-actlen;
+   buf = KERNADDR(xfer-dmabuf, 0);
if (info-id  0) {
len--;
-   memcpy(info-data, xfer-buffer + 1, len);
+   memcpy(info-data, buf + 1, len);
} else {
-   memcpy(info-data, xfer-buffer, len);
+   memcpy(info-data, buf, len);
}
}
info-callback(info-priv, info-id, info-data, len);
Index: usbdi.c
===
RCS file: /cvs/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.80
diff -u -p -r1.80 usbdi.c
--- usbdi.c 12 Feb 2015 05:07:52 -  1.80
+++ usbdi.c 14 Feb 2015 15:18:47 -
@@ -748,6 +748,15 @@ usb_transfer_complete(struct usbd_xfer *
memcpy(xfer-buffer, KERNADDR(xfer-dmabuf, 0), xfer-actlen);
}
 
+   if (!xfer-status  xfer-actlen  xfer-length 
+   !(xfer-flags  USBD_SHORT_XFER_OK)) {
+   DPRINTFN(-1,(usb_transfer_complete: short transfer %d%d\n,
+   xfer-actlen, xfer-length));
+   xfer-status = USBD_SHORT_XFER;
+   }
+   if (xfer-callback)
+   xfer-callback(xfer, xfer-priv, xfer-status);
+
/* if we allocated the buffer in usbd_transfer() we free it here. */
if (xfer-rqflags  URQ_AUTO_DMABUF) {
if (!pipe-repeat) {
@@ -774,22 +783,7 @@ usb_transfer_complete(struct usbd_xfer *
[pipe-endpoint-edesc-bmAttributes  UE_XFERTYPE];
 
xfer-done = 1;
-   if (!xfer-status  xfer-actlen  xfer-length 
-   !(xfer-flags  USBD_SHORT_XFER_OK)) {
-   DPRINTFN(-1,(usb_transfer_complete: short

Re: USBD_NO_COPY problems

2015-02-13 Thread David Higgs
On Friday, February 13, 2015, Martin Pieuchot mpieuc...@nolizard.org
wrote:

 On 13/02/15(Fri) 00:28, David Higgs wrote:
  I guess nobody else has tried calling uhidev_get_report_async() yet.  :)
 
  First I was getting a NULL pointer deref in the uhidev async callback.
  Then I realized that due to USBD_NO_COPY, xfer-buffer was always
  NULL.  Next, I tried to use the DMA buffer, but I ended up in DDB in a
  very cryptic way.  I believe this is because the DMA buffer isn't
  available when the callback is invoked.
 
  For the async callback to get a valid dmabuf, it needs to be invoked
  prior to usb_freemem() in usbd_transfer_complete().  The xfer-status
  determination would need to move up too.  I'd do this myself but I
  don't understand the logic and ordering of pipe-repeat stuff, and am
  concerned about unintentionally breaking other devices.
 
  This is partially my fault, because I tested the original diff that
  added the USBD_NO_COPY semantics to verify that it didn't break my
  synchronous code paths, but hadn't yet written anything for upd(4) to
  check the async ones.

 Does the diff below help?


 Partially but not enough.  I had already figured out that I needed that
to solve the NULL pointer dereference.  See my 2nd paragraph above.

Index: uhidev.c
 ===
 RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
 retrieving revision 1.69
 diff -u -p -r1.69 uhidev.c
 --- uhidev.c22 Jan 2015 10:27:47 -  1.69
 +++ uhidev.c13 Feb 2015 05:58:06 -
 @@ -55,6 +55,7 @@
  #include dev/usb/usbdivar.h
  #include dev/usb/hid.h
  #include dev/usb/usb_quirks.h
 +#include dev/usb/usb_mem.h

  #include dev/usb/uhidev.h

 @@ -747,15 +748,17 @@ void
  uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv,
 usbd_status err)
  {
 struct uhidev_async_info *info = priv;
 +   char *buffer;
 int len = -1;

 if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
 +   buffer = KERNADDR(xfer-dmabuf, 0);
 len = xfer-actlen;
 if (info-id  0) {
 len--;
 -   memcpy(info-data, xfer-buffer + 1, len);
 +   memcpy(info-data, buffer + 1, len);
 } else {
 -   memcpy(info-data, xfer-buffer, len);
 +   memcpy(info-data, buffer, len);
 }
 }
 info-callback(info-priv, info-id, info-data, len);



USBD_NO_COPY problems

2015-02-12 Thread David Higgs
I guess nobody else has tried calling uhidev_get_report_async() yet.  :)

First I was getting a NULL pointer deref in the uhidev async callback.
Then I realized that due to USBD_NO_COPY, xfer-buffer was always
NULL.  Next, I tried to use the DMA buffer, but I ended up in DDB in a
very cryptic way.  I believe this is because the DMA buffer isn't
available when the callback is invoked.

For the async callback to get a valid dmabuf, it needs to be invoked
prior to usb_freemem() in usbd_transfer_complete().  The xfer-status
determination would need to move up too.  I'd do this myself but I
don't understand the logic and ordering of pipe-repeat stuff, and am
concerned about unintentionally breaking other devices.

This is partially my fault, because I tested the original diff that
added the USBD_NO_COPY semantics to verify that it didn't break my
synchronous code paths, but hadn't yet written anything for upd(4) to
check the async ones.

Thanks.

--david



Re: Fewer malloc() memcpy() in USB land

2015-01-21 Thread David Higgs
On Fri, Jan 9, 2015 at 2:07 PM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 09/01/15(Fri) 12:36, David Higgs wrote:
 On Fri, Jan 9, 2015 at 9:00 AM, Martin Pieuchot mpieuc...@nolizard.org 
 wrote:
  As pointed out by David Higgs, uhidev report functions do a lot of
  memory allocations and copies between buffers.  This is not uncommon
  in USB land due to way DMA buffers are handled.
 
  One way to reduce the number of copies is to submit a transfer with
  the USBD_NO_COPY flag.  Without it the kernel does two to three copies:
 
(stack/driver array --) malloc'ed array -- DMA reacheable array
 
  This is not limited to uhidev functions.  That's also done for every
  transfer sent through an interrupt pipe or for every control request
  with data.
 
  I'd like to slowly change the stack such that USBD_NO_COPY becomes the
  default behavior.  This would first reduces the number of buffer copies
  and then allow umass(4) to directly use the DMA reachable buffers
  provided by the SCSI stack, which should *at least* reduce the CPU usage
  when using USB drives.
 
  Here's a diff about uhidev(4) to illustrate the changes I'm talking
  about.
 
  Comments, ok?
 

 See inline.  Reviewed to the best of my ability/eyesight via
 variable-width webmail.
 [...]
  +
  +   if (id  0)
  +   len++;
  +
  +   buf = usbd_alloc_buffer(xfer, len);
  +   if (buf == NULL)
  +   return (-1);

 You forgot to free xfer in this error path.

 Indeed!

  @@ -586,6 +585,7 @@ usbd_status
   usbd_clear_endpoint_stall_async(struct usbd_pipe *pipe)
   {
  struct usbd_device *dev = pipe-device;
  +   struct usbd_xfer *xfer;
  usb_device_request_t req;
  usbd_status err;
 
  @@ -596,7 +596,12 @@ usbd_clear_endpoint_stall_async(struct u
  USETW(req.wValue, UF_ENDPOINT_HALT);
  USETW(req.wIndex, pipe-endpoint-edesc-bEndpointAddress);
  USETW(req.wLength, 0);
  -   err = usbd_do_request_async(dev, req, 0, 0, 0);
  +
  +   xfer = usbd_alloc_xfer(dev);
  +   if (xfer == NULL)
  +   return (USBD_NOMEM);
  +
  +   err = usbd_request_async(xfer, req, NULL, NULL);

 Missing xfer cleanup here too, I think.

 Here it's fine, as soon as you call usbd_request_async() the xfer will be
 freed.

 Updated diff below.


The updated diff appears to works for me and I don't see any further
issues upon review.  No behavior changes when applied to a snapshot +
HEAD kernel as of this evening.  Tested via repeated sysctl reads of
upd(4) sensor info and a few device detach/attach events.

--david



Re: Fewer malloc() memcpy() in USB land

2015-01-09 Thread David Higgs
On Fri, Jan 9, 2015 at 9:00 AM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 As pointed out by David Higgs, uhidev report functions do a lot of
 memory allocations and copies between buffers.  This is not uncommon
 in USB land due to way DMA buffers are handled.

 One way to reduce the number of copies is to submit a transfer with
 the USBD_NO_COPY flag.  Without it the kernel does two to three copies:

   (stack/driver array --) malloc'ed array -- DMA reacheable array

 This is not limited to uhidev functions.  That's also done for every
 transfer sent through an interrupt pipe or for every control request
 with data.

 I'd like to slowly change the stack such that USBD_NO_COPY becomes the
 default behavior.  This would first reduces the number of buffer copies
 and then allow umass(4) to directly use the DMA reachable buffers
 provided by the SCSI stack, which should *at least* reduce the CPU usage
 when using USB drives.

 Here's a diff about uhidev(4) to illustrate the changes I'm talking
 about.

 Comments, ok?


See inline.  Reviewed to the best of my ability/eyesight via
variable-width webmail.

 Index: uhidev.c
 ===
 RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
 retrieving revision 1.68
 diff -u -p -r1.68 uhidev.c
 --- uhidev.c9 Jan 2015 12:09:51 -   1.68
 +++ uhidev.c9 Jan 2015 13:31:36 -
 @@ -671,18 +671,28 @@ int
  uhidev_set_report_async(struct uhidev_softc *sc, int type, int id, void 
 *data,
  int len)
  {
 +   struct usbd_xfer *xfer;
 usb_device_request_t req;
 -   char *buf = data;
 int actlen = len;
 +   char *buf;
 +
 +   xfer = usbd_alloc_xfer(sc-sc_udev);
 +   if (xfer == NULL)
 +   return (-1);
 +
 +   if (id  0)
 +   len++;
 +
 +   buf = usbd_alloc_buffer(xfer, len);
 +   if (buf == NULL)
 +   return (-1);

You forgot to free xfer in this error path.


 /* Prepend the reportID. */
 if (id  0) {
 -   len++;
 -   buf = malloc(len, M_TEMP, M_NOWAIT);
 -   if (buf == NULL)
 -   return (-1);
 buf[0] = id;
 memcpy(buf + 1, data, len - 1);
 +   } else {
 +   memcpy(buf, data, len);
 }

 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
 @@ -691,17 +701,9 @@ uhidev_set_report_async(struct uhidev_so
 USETW(req.wIndex, sc-sc_ifaceno);
 USETW(req.wLength, len);

 -   if (usbd_do_request_async(sc-sc_udev, req, buf, NULL, NULL))
 +   if (usbd_request_async(xfer, req, NULL, NULL))
 actlen = -1;

 -   /*
 -* Since report requests are write-only it is safe to free
 -* the buffer right after submitting the transfer because
 -* it won't be used afterward.
 -*/
 -   if (id  0)
 -   free(buf, M_TEMP, len);
 -
 return (actlen);
  }

 @@ -750,11 +752,11 @@ uhidev_get_report_async_cb(struct usbd_x
 if (info-id  0) {
 len--;
 memcpy(info-data, xfer-buffer + 1, len);
 +   } else {
 +   memcpy(info-data, xfer-buffer, len);
 }
 }
 info-callback(info-priv, info-id, info-data, len);
 -   if (info-id  0)
 -   free(xfer-buffer, M_TEMP, xfer-length);
 free(info, M_TEMP, sizeof(*info));
 usbd_free_xfer(xfer);
  }
 @@ -763,42 +765,48 @@ int
  uhidev_get_report_async(struct uhidev_softc *sc, int type, int id, void 
 *data,
  int len, void *priv, void (*callback)(void *, int, void *, int))
  {
 +   struct usbd_xfer *xfer;
 usb_device_request_t req;
 struct uhidev_async_info *info;
 -   char *buf = data;
 int actlen = len;
 +   void *buf;
 +
 +   xfer = usbd_alloc_xfer(sc-sc_udev);
 +   if (xfer == NULL)
 +   return (-1);
 +
 +   if (id  0)
 +   len++;
 +
 +   buf = usbd_alloc_buffer(xfer, len);
 +   if (buf == NULL) {
 +   usbd_free_xfer(xfer);
 +   return (-1);
 +   }

 info = malloc(sizeof(*info), M_TEMP, M_NOWAIT);
 -   if (info == NULL)
 +   if (info == NULL) {
 +   usbd_free_xfer(xfer);
 return (-1);
 +   }

 info-callback = callback;
 info-priv = priv;
 info-data = data;
 info-id = id;

 -   if (id  0) {
 -   len++;
 -   buf = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
 -   if (buf == NULL) {
 -   free(info, M_TEMP, sizeof(*info));
 -   return (-1);
 -   }
 -   }
 -
 req.bmRequestType = UT_READ_CLASS_INTERFACE;
 req.bRequest = UR_GET_REPORT;
 USETW2(req.wValue, type, id);
 USETW(req.wIndex, sc-sc_ifaceno);
 USETW(req.wLength, len

Re: Fix upd(4) sensor refresh

2014-12-20 Thread David Higgs
On Fri, Dec 19, 2014 at 8:55 AM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 19/12/14(Fri) 08:04, David Higgs wrote:
 Split upd_update_sensors() behavior to gather all values prior to updating 
 sensor contents.

 Because sensors were updated in report_ID order, it could take multiple 
 passes of upd_refresh() to update some sensors.  Specifically, 
 battery-related sensors prior to a change in BatteryPresent would be 
 stale/incorrect until the 2nd call to upd_refresh().  Also, change a 
 confusing DPRINTF of report_ID from un-prefixed hex to decimal, to be 
 consistent.

 What you're saying is that querying HUB_BATTERY_PRESENT after 6 sensors
 that depend on its value does not make sense, right?

Correct.

 Well in this case I don't think that sensors should be queried in
 reportID order.  I even don't think that sensors should be queried at
 all if we're going to discard the result anyway.  It might not matter
 that much right now, but if the number of queried sensors grow
 s significantly we might end up waiting a lot of time in upd_refresh()
 prior to updating anything.

Querying by report_ID minimizes the number of requests, because
multiple sensors can be batched into the same report_ID.  I don't know
if there are any rules that determine how items are batched, so there
may be pathologically bad results.

 This fix is needed for future improvements, where output or behavior of 
 certain sensors depends on the current value of more than one report (e.g. 
 RemainingCapacity should actually depend on CapacityMode).

 But do you need to read the value of CapacityMode more than once, at the
 begging or when you modify it?

True.  CapacityMode shouldn't automatically change and can be read
once (and/or maybe updated) at attach-time.  I see no reason to expose
this setting for users to change.

 Anyway, when we discussed that with Andre, I suggested to have a table
 containing all sensors depending on an other one.   This way you can
 start by querying HUB_BATTERY_PRESENT and if it is present, query the
 others.   Another advantage is that it will simplify the code because
 all the sensors in a table will be in the same page.

This sounds good.  I will revisit the Power/Battery spec and see what
future sensors might require dependent behavior.

 Since you're doing some great job with upd(4), here's another idea.  Did
 you consider updating the values of the sensors via an asynchronous
 function and a callback?  This way the thread does not need to way for
 the previous queries.   That would involve adding a new function, let's
 say uhidev_get_report_async() that takes a custom callback since there's
 no such API for the moment.

This sounds like a good idea, but batched report_ID values can produce
redundant USB queries or will require additional logic/caching to
minimize this redundancy.  I'm new to all this, and am not sure how to
decide which trade-offs to make.

Thanks.

--david



Re: Better/more upd(4) timedelta sensors

2014-12-19 Thread David Higgs
On Fri, Dec 19, 2014 at 7:17 AM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 Hello David,

 On 18/12/14(Thu) 00:45, David Higgs wrote:
 While my device does not seem to provide AtRateTimeToFull or 
 AtRateTimeToEmpty, it does have RunTimeToEmpty.  Then I found that 
 SENSOR_TIMEDELTA values are in nanoseconds and that scaling for them was 
 never implemented correctly.

 I am confused by the spec [1], though; see 4.2.5 - Battery Measures.  The 
 reported values are supposedly in minutes but hid_info.unit is 0x1001 
 (seconds) and observation of RunTimeToEmpty appears to agree.  I don't see 
 any other drivers in the tree that pay attention to unit or unit_exponent 
 fields, and don't want to go down a rabbit hole if there's no interest.

 As usual, feedback is welcome.

 Table 1 of section 3.2.3 indicates that the physical unit for time
 reports are in seconds.  So I guess it is a mistake in the document.

 I like your diff but I'd prefer to see the scaling done based on the
 unit rather than the name.  Why not adding new defines for the various
 Physical Unit defined in the table and do the switch on hitem.unit? And
 what about the exponent?


Thanks for looking at this.  I've rethought my approach to upd(4) a
bit, and will be addressing bugs prior to adding new sensors.  There
will be a diff to address units in a more coherent fashion soon.

--david



Fix upd(4) sensor refresh

2014-12-19 Thread David Higgs
Split upd_update_sensors() behavior to gather all values prior to updating 
sensor contents.

Because sensors were updated in report_ID order, it could take multiple passes 
of upd_refresh() to update some sensors.  Specifically, battery-related sensors 
“prior” to a change in BatteryPresent would be stale/incorrect until the 2nd 
call to upd_refresh().  Also, change a confusing DPRINTF of report_ID from 
un-prefixed hex to decimal, to be consistent.

This fix is needed for future improvements, where output or behavior of certain 
sensors depends on the current value of more than one report (e.g. 
RemainingCapacity should actually depend on CapacityMode).

As always, feedback is welcome.

--david


Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.12
diff -u -p -r1.12 upd.c
--- upd.c   11 Dec 2014 18:50:32 -  1.12
+++ upd.c   19 Dec 2014 05:33:14 -
@@ -77,6 +77,8 @@ struct upd_report {
 struct upd_sensor {
struct ksensor  ksensor;
struct hid_item hitem;
+   int raw_value;
+   int value_read;
int attached;
 };
 
@@ -98,7 +100,8 @@ void upd_attach(struct device *, struct 
 int  upd_detach(struct device *, int);
 
 void upd_refresh(void *);
-void upd_update_sensors(struct upd_softc *, uint8_t *, unsigned int, int);
+void upd_update_values(struct upd_softc *, uint8_t *, unsigned int, int);
+void upd_update_sensors(struct upd_softc *);
 void upd_intr(struct uhidev *, void *, uint);
 struct upd_usage_entry *upd_lookup_usage_entry(const struct hid_item *);
 struct upd_sensor *upd_lookup_sensor(struct upd_softc *, int, int);
@@ -275,7 +278,7 @@ upd_refresh(void *arg)
UHID_FEATURE_REPORT, repid, buf, report-size);
 
if (actlen == -1) {
-   DPRINTF((upd: failed to get report id=%02x\n, repid));
+   DPRINTF((upd: failed to get report id=%d\n, repid));
continue;
}
 
@@ -283,8 +286,10 @@ upd_refresh(void *arg)
if (actlen  report-size)
report-size = actlen;
 
-   upd_update_sensors(sc, buf, report-size, repid);
+   upd_update_values(sc, buf, report-size, repid);
}
+
+   upd_update_sensors(sc);
 }
 
 struct upd_usage_entry *
@@ -318,33 +323,48 @@ upd_lookup_sensor(struct upd_softc *sc, 
 }
 
 void
-upd_update_sensors(struct upd_softc *sc, uint8_t *buf, unsigned int len,
+upd_update_values(struct upd_softc *sc, uint8_t *buf, unsigned int len,
 int repid)
 {
struct upd_sensor   *sensor;
-   ulong   hdata, batpres;
-   ulong   adjust;
int i;
 
+   for (i = 0; i  sc-sc_num_sensors; i++) {
+   sensor = sc-sc_sensors[i];
+   if (sensor-hitem.report_ID == repid  sensor-attached) {
+   sensor-value_read = 1;
+   sensor-raw_value =
+   hid_get_data(buf, len, sensor-hitem.loc);
+   DPRINTF((%s: repid=%d, %s value=%d\n,
+   sc-sc_sensordev.xname, repid,
+   sensor-ksensor.desc, sensor-raw_value));
+   }
+   }
+}
+
+void
+upd_update_sensors(struct upd_softc *sc)
+{
+   struct upd_sensor   *sensor;
+   ulong   adjust;
+   int i, batpres = 0;
+
sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT);
-   batpres = sensor ? sensor-ksensor.value : -1;
+   if (sensor  sensor-value_read)
+   batpres = sensor-raw_value;
 
for (i = 0; i  sc-sc_num_sensors; i++) {
sensor = sc-sc_sensors[i];
-   if (!(sensor-hitem.report_ID == repid  sensor-attached))
+   sensor-ksensor.flags |= SENSOR_FINVALID;
+   sensor-ksensor.status = SENSOR_S_UNKNOWN;
+   if (!sensor-value_read)
continue;
 
-   /* invalidate battery dependent sensors */
+   /* ignore battery sensors when no battery present */
if (HID_GET_USAGE_PAGE(sensor-hitem.usage) == HUP_BATTERY 
-   batpres = 0) {
-   /* exception to the battery sensor itself */
-   if (HID_GET_USAGE(sensor-hitem.usage) !=
-   HUB_BATTERY_PRESENT) {
-   sensor-ksensor.status = SENSOR_S_UNKNOWN;
-   sensor-ksensor.flags |= SENSOR_FINVALID;
-   continue;
-   }
-   }
+   HID_GET_USAGE(sensor-hitem.usage) != HUB_BATTERY_PRESENT 
+   !batpres)
+   continue;
 
switch 

Unit descriptions in sensors.h

2014-12-18 Thread David Higgs
For consistency.

--david


Index: sensors.h
===
RCS file: /cvs/src/sys/sys/sensors.h,v
retrieving revision 1.33
diff -u -p -r1.33 sensors.h
--- sensors.h   4 Nov 2013 02:41:49 -   1.33
+++ sensors.h   18 Dec 2014 18:16:07 -
@@ -38,11 +38,11 @@ enum sensor_type {
SENSOR_OHMS,/* resistance */
SENSOR_WATTS,   /* power (muW) */
SENSOR_AMPS,/* current (muA) */
-   SENSOR_WATTHOUR,/* power capacity */
-   SENSOR_AMPHOUR, /* power capacity */
+   SENSOR_WATTHOUR,/* power capacity (muWh) */
+   SENSOR_AMPHOUR, /* power capacity (muWh) */
SENSOR_INDICATOR,   /* boolean indicator */
SENSOR_INTEGER, /* generic integer value */
-   SENSOR_PERCENT, /* percent */
+   SENSOR_PERCENT, /* percent (m%) */
SENSOR_LUX, /* illuminance (mulx) */
SENSOR_DRIVE,   /* disk */
SENSOR_TIMEDELTA,   /* system time error (nSec) */



Re: Unit descriptions in sensors.h

2014-12-18 Thread David Higgs
Bah.  One of those should be (muAh).

--david



Re: Unit descriptions in sensors.h

2014-12-18 Thread David Higgs

On Dec 18, 2014, at 1:48 PM, David Higgs hig...@gmail.com wrote:

 Bah.  One of those should be (muAh).
 

Take two.

--david

Index: sensors.h
===
RCS file: /cvs/src/sys/sys/sensors.h,v
retrieving revision 1.33
diff -u -p -r1.33 sensors.h
--- sensors.h   4 Nov 2013 02:41:49 -   1.33
+++ sensors.h   18 Dec 2014 19:36:51 -
@@ -38,11 +38,11 @@ enum sensor_type {
SENSOR_OHMS,/* resistance */
SENSOR_WATTS,   /* power (muW) */
SENSOR_AMPS,/* current (muA) */
-   SENSOR_WATTHOUR,/* power capacity */
-   SENSOR_AMPHOUR, /* power capacity */
+   SENSOR_WATTHOUR,/* power capacity (muWh) */
+   SENSOR_AMPHOUR, /* power capacity (muAh) */
SENSOR_INDICATOR,   /* boolean indicator */
SENSOR_INTEGER, /* generic integer value */
-   SENSOR_PERCENT, /* percent */
+   SENSOR_PERCENT, /* percent (m%) */
SENSOR_LUX, /* illuminance (mulx) */
SENSOR_DRIVE,   /* disk */
SENSOR_TIMEDELTA,   /* system time error (nSec) */




Better/more upd(4) timedelta sensors

2014-12-17 Thread David Higgs
While my device does not seem to provide AtRateTimeToFull or AtRateTimeToEmpty, 
it does have RunTimeToEmpty.  Then I found that SENSOR_TIMEDELTA values are in 
nanoseconds and that scaling for them was never implemented correctly.

I am confused by the spec [1], though; see 4.2.5 - Battery Measures.  The 
reported values are supposedly in minutes but hid_info.unit is 0x1001 (seconds) 
and observation of RunTimeToEmpty appears to agree.  I don’t see any other 
drivers in the tree that pay attention to unit or unit_exponent fields, and 
don’t want to go down a rabbit hole if there’s no interest.

As usual, feedback is welcome.

[1] http://www.usb.org/developers/hidpage/pdcv10.pdf

--david


Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.12
diff -u -p -r1.12 upd.c
--- upd.c   11 Dec 2014 18:50:32 -  1.12
+++ upd.c   18 Dec 2014 05:02:30 -
@@ -66,7 +66,11 @@ static struct upd_usage_entry upd_usage_
{ HUP_BATTERY,  HUB_AC_PRESENT,
SENSOR_INDICATOR,ACPresent },
{ HUP_BATTERY,  HUB_ATRATE_TIMETOFULL,
-   SENSOR_TIMEDELTA,AtRateTimeToFull }
+   SENSOR_TIMEDELTA,AtRateTimeToFull },
+   { HUP_BATTERY,  HUB_ATRATE_TIMETOEMPTY,
+   SENSOR_TIMEDELTA,AtRateTimeToEmpty },
+   { HUP_BATTERY,  HUB_RUNTIMETO_EMPTY,
+   SENSOR_TIMEDELTA,RunTimeToEmpty },
 };
 
 struct upd_report {
@@ -322,9 +326,9 @@ upd_update_sensors(struct upd_softc *sc,
 int repid)
 {
struct upd_sensor   *sensor;
-   ulong   hdata, batpres;
-   ulong   adjust;
-   int i;
+   int64_t adjust;
+   ulong   batpres;
+   int hdata, i;
 
sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT);
batpres = sensor ? sensor-ksensor.value : -1;
@@ -353,6 +357,11 @@ upd_update_sensors(struct upd_softc *sc,
case HUB_FULLCHARGE_CAPACITY:
adjust = 1000; /* scale adjust */
break;
+   case HUB_ATRATE_TIMETOFULL:
+   case HUB_ATRATE_TIMETOEMPTY:
+   case HUB_RUNTIMETO_EMPTY:
+   adjust = 10LL; /* XXX not minutes? */
+   break;
default:
adjust = 1; /* no scale adjust */
break;
@@ -363,7 +372,7 @@ upd_update_sensors(struct upd_softc *sc,
sensor-ksensor.value = hdata * adjust;
sensor-ksensor.status = SENSOR_S_OK;
sensor-ksensor.flags = ~SENSOR_FINVALID;
-   DPRINTF((%s: hidget data: %lu\n,
+   DPRINTF((%s: hidget data: %d\n,
sc-sc_sensordev.xname, hdata));
}
 }




Re: upd(4) buggy firmware

2014-12-11 Thread David Higgs
On Thu, Dec 11, 2014 at 6:22 AM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 Thanks for all your comments.  I though a bit more about this change and
 decided to:

   - Simply return the number of bytes written/read upon success and -1
 otherwise (à la read/write).  This allows us to remove some usages
 of usbd_status when we are not directly manipulating a xfer
 object.

   - Always consider a short transfer for SET requests as failures.

 So the diff below includes your changes to upd(4) that I'll commit
 separately if you're ok.

 Concerning your remark about the USB_SET_IMMED ioctl(2), it doesn't
 really matter, this interface is not used and should be removed.


Aside from what kettenis@ already saw, I also notice that
uhidev_use_rdesc and ukbd_set_leds don't check their set_report calls,
but that was the case in the previous code too.

Other than that, the diff looks good and runs my UPS fine.  Commit in
whatever chunks you deem appropriate.

Thanks.

--david



upd(4) status

2014-12-11 Thread David Higgs
Now that my upd(4) is working (thanks to all involved), I’m looking to improve 
behavior a bit.  Let’s add some state transitions to the sensors.

Feedback is welcome.

--david


## before
[vm@vm usb]$ sysctl hw.sensors.upd0
hw.sensors.upd0.indicator0=Off (Charging), OK
hw.sensors.upd0.indicator1=Off (Discharging), OK
hw.sensors.upd0.indicator2=On (ACPresent), OK
hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
hw.sensors.upd0.indicator4=On (BatteryPresent), OK
hw.sensors.upd0.percent0=100.00% (RemainingCapacity), OK
hw.sensors.upd0.percent1=100.00% (FullChargeCapacity), OK

## AC power loss
[vm@vm usb]$ sysctl hw.sensors.upd0
hw.sensors.upd0.indicator0=Off (Charging), OK
hw.sensors.upd0.indicator1=On (Discharging), WARNING
hw.sensors.upd0.indicator2=Off (ACPresent), WARNING
hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
hw.sensors.upd0.indicator4=On (BatteryPresent), OK
hw.sensors.upd0.percent0=95.00% (RemainingCapacity), OK
hw.sensors.upd0.percent1=100.00% (FullChargeCapacity), OK

## AC power restored
[vm@vm usb]$ sysctl hw.sensors.upd0 
hw.sensors.upd0.indicator0=On (Charging), WARNING
hw.sensors.upd0.indicator1=Off (Discharging), OK
hw.sensors.upd0.indicator2=On (ACPresent), OK
hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
hw.sensors.upd0.indicator4=On (BatteryPresent), OK
hw.sensors.upd0.percent0=97.00% (RemainingCapacity), OK
hw.sensors.upd0.percent1=100.00% (FullChargeCapacity), OK


Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.12
diff -u -p -r1.12 upd.c
--- upd.c   11 Dec 2014 18:50:32 -  1.12
+++ upd.c   12 Dec 2014 00:32:09 -
@@ -324,6 +324,7 @@ upd_update_sensors(struct upd_softc *sc,
struct upd_sensor   *sensor;
ulong   hdata, batpres;
ulong   adjust;
+   enum sensor_status  status;
int i;
 
sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT);
@@ -346,6 +347,10 @@ upd_update_sensors(struct upd_softc *sc,
}
}
 
+   adjust = 1;
+   status = SENSOR_S_OK;
+   hdata = hid_get_data(buf, len, sensor-hitem.loc);
+
switch (HID_GET_USAGE(sensor-hitem.usage)) {
case HUB_REL_STATEOF_CHARGE:
case HUB_ABS_STATEOF_CHARGE:
@@ -353,15 +358,28 @@ upd_update_sensors(struct upd_softc *sc,
case HUB_FULLCHARGE_CAPACITY:
adjust = 1000; /* scale adjust */
break;
+   case HUB_CHARGING:
+   case HUB_DISCHARGING:
+   if (hdata)
+   status = SENSOR_S_WARN;
+   break;
+   case HUB_BATTERY_PRESENT:
+   if (!hdata)
+   status = SENSOR_S_CRIT;
+   break;
+   case HUP_SHUTDOWN_IMMINENT:
+   if (hdata)
+   status = SENSOR_S_CRIT;
+   break;
+   case HUB_AC_PRESENT:
+   if (!hdata)
+   status = SENSOR_S_WARN;
default:
-   adjust = 1; /* no scale adjust */
break;
}
 
-   hdata = hid_get_data(buf, len, sensor-hitem.loc);
-
sensor-ksensor.value = hdata * adjust;
-   sensor-ksensor.status = SENSOR_S_OK;
+   sensor-ksensor.status = status;
sensor-ksensor.flags = ~SENSOR_FINVALID;
DPRINTF((%s: hidget data: %lu\n,
sc-sc_sensordev.xname, hdata));




Improve upd(4) battery present check

2014-12-11 Thread David Higgs
First, I think the BatteryPresent check has a signedness problem.  Second, I 
think that it should check for sensor validity too, so it doesn’t use stale 
values if BatteryPresent somehow goes straight from present to invalid.

This diff should fix both things, in theory.  Compiled and running without 
adverse effects.  I did not pull apart my UPS while it’s actively running to 
confirm, though.

--david

Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.12
diff -u -p -r1.12 upd.c
--- upd.c   11 Dec 2014 18:50:32 -  1.12
+++ upd.c   12 Dec 2014 02:11:09 -
@@ -322,12 +322,14 @@ upd_update_sensors(struct upd_softc *sc,
 int repid)
 {
struct upd_sensor   *sensor;
-   ulong   hdata, batpres;
+   ulong   hdata;
ulong   adjust;
-   int i;
+   int i, batpres = 0;
 
sensor = upd_lookup_sensor(sc, HUP_BATTERY, HUB_BATTERY_PRESENT);
-   batpres = sensor ? sensor-ksensor.value : -1;
+   if (sensor  !(sensor-ksensor.flags  SENSOR_FINVALID) 
+   sensor-ksensor.value)
+   batpres = 1;
 
for (i = 0; i  sc-sc_num_sensors; i++) {
sensor = sc-sc_sensors[i];
@@ -336,7 +338,7 @@ upd_update_sensors(struct upd_softc *sc,
 
/* invalidate battery dependent sensors */
if (HID_GET_USAGE_PAGE(sensor-hitem.usage) == HUP_BATTERY 
-   batpres = 0) {
+   !batpres) {
/* exception to the battery sensor itself */
if (HID_GET_USAGE(sensor-hitem.usage) !=
HUB_BATTERY_PRESENT) {




vic0: no link on recent i386 /bsd.rd

2014-12-09 Thread David Higgs
Working and non-working dmesgs from the same VM below.  Let me know if
any more info is needed.  If this is already known, sorry for the
noise.

--david

# does not work

OpenBSD 5.6-current (RAMDISK_CD) #555: Tue Dec  9 00:50:21 MST 2014
dera...@i386.openbsd.org:/usr/src/sys/arch/i386/compile/RAMDISK_CD
cpu0: Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz (GenuineIntel
686-class) 2.42 GHz
cpu0: 
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,NXE,LONG,SSE3,SSSE3,CX16,LAHF,PERF,ITSC
real mem  = 267907072 (255MB)
avail mem = 255856640 (244MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 09/20/12, BIOS32 rev. 0 @
0xfd780, SMBIOS rev. 2.4 @ 0xe0010 (364 entries)
bios0: vendor Phoenix Technologies LTD version 6.00 date 09/20/2012
bios0: VMware, Inc. VMware Virtual Platform
acpi0 at bios0: rev 2
acpi0: sleep states S0 S1 S4 S5
acpi0: tables DSDT FACP BOOT APIC MCFG SRAT HPET WAET
acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: apic clock running at 65MHz
ioapic0 at mainbus0: apid 1 pa 0xfec0, version 11, 24 pins
acpiprt0 at acpi0: bus 0 (PCI0)
bios0: ROM list: 0xc/0x8000 0xc8000/0x1000 0xdc000/0x4000! 0xe/0x8000!
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 Intel 82443BX AGP rev 0x01
ppb0 at pci0 dev 1 function 0 Intel 82443BX AGP rev 0x01
pci1 at ppb0 bus 1
pcib0 at pci0 dev 7 function 0 Intel 82371AB PIIX4 ISA rev 0x08
pciide0 at pci0 dev 7 function 1 Intel 82371AB IDE rev 0x01: DMA,
channel 0 configured to compatibility, channel 1 configured to
compatibility
wd0 at pciide0 channel 0 drive 0: VMware Virtual IDE Hard Drive
wd0: 64-sector PIO, LBA, 8192MB, 16777216 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 disabled (no drives)
Intel 82371AB Power rev 0x08 at pci0 dev 7 function 3 not configured
VMware VMCI rev 0x10 at pci0 dev 7 function 7 not configured
vga1 at pci0 dev 15 function 0 VMware SVGA II rev 0x00
vga1: aperture needed
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
ppb1 at pci0 dev 17 function 0 VMware PCI rev 0x02
pci2 at ppb1 bus 2
vic0 at pci2 dev 0 function 0 AMD 79c970 PCnet-PCI rev 0x10: apic 1
int 18, address 00:0c:29:23:6c:31
ppb2 at pci0 dev 21 function 0 VMware PCIE rev 0x01
pci3 at ppb2 bus 3
ppb3 at pci0 dev 21 function 1 VMware PCIE rev 0x01
pci4 at ppb3 bus 4
ppb4 at pci0 dev 21 function 2 VMware PCIE rev 0x01
pci5 at ppb4 bus 5
ppb5 at pci0 dev 21 function 3 VMware PCIE rev 0x01
pci6 at ppb5 bus 6
ppb6 at pci0 dev 21 function 4 VMware PCIE rev 0x01
pci7 at ppb6 bus 7
ppb7 at pci0 dev 21 function 5 VMware PCIE rev 0x01
pci8 at ppb7 bus 8
ppb8 at pci0 dev 21 function 6 VMware PCIE rev 0x01
pci9 at ppb8 bus 9
ppb9 at pci0 dev 21 function 7 VMware PCIE rev 0x01
pci10 at ppb9 bus 10
ppb10 at pci0 dev 22 function 0 VMware PCIE rev 0x01
pci11 at ppb10 bus 11
ppb11 at pci0 dev 22 function 1 VMware PCIE rev 0x01
pci12 at ppb11 bus 12
ppb12 at pci0 dev 22 function 2 VMware PCIE rev 0x01
pci13 at ppb12 bus 13
ppb13 at pci0 dev 22 function 3 VMware PCIE rev 0x01
pci14 at ppb13 bus 14
ppb14 at pci0 dev 22 function 4 VMware PCIE rev 0x01
pci15 at ppb14 bus 15
ppb15 at pci0 dev 22 function 5 VMware PCIE rev 0x01
pci16 at ppb15 bus 16
ppb16 at pci0 dev 22 function 6 VMware PCIE rev 0x01
pci17 at ppb16 bus 17
ppb17 at pci0 dev 22 function 7 VMware PCIE rev 0x01
pci18 at ppb17 bus 18
ppb18 at pci0 dev 23 function 0 VMware PCIE rev 0x01
pci19 at ppb18 bus 19
ppb19 at pci0 dev 23 function 1 VMware PCIE rev 0x01
pci20 at ppb19 bus 20
ppb20 at pci0 dev 23 function 2 VMware PCIE rev 0x01
pci21 at ppb20 bus 21
ppb21 at pci0 dev 23 function 3 VMware PCIE rev 0x01
pci22 at ppb21 bus 22
ppb22 at pci0 dev 23 function 4 VMware PCIE rev 0x01
pci23 at ppb22 bus 23
ppb23 at pci0 dev 23 function 5 VMware PCIE rev 0x01
pci24 at ppb23 bus 24
ppb24 at pci0 dev 23 function 6 VMware PCIE rev 0x01
pci25 at ppb24 bus 25
ppb25 at pci0 dev 23 function 7 VMware PCIE rev 0x01
pci26 at ppb25 bus 26
ppb26 at pci0 dev 24 function 0 VMware PCIE rev 0x01
pci27 at ppb26 bus 27
ppb27 at pci0 dev 24 function 1 VMware PCIE rev 0x01
pci28 at ppb27 bus 28
ppb28 at pci0 dev 24 function 2 VMware PCIE rev 0x01
pci29 at ppb28 bus 29
ppb29 at pci0 dev 24 function 3 VMware PCIE rev 0x01
pci30 at ppb29 bus 30
ppb30 at pci0 dev 24 function 4 VMware PCIE rev 0x01
pci31 at ppb30 bus 31
ppb31 at pci0 dev 24 function 5 VMware PCIE rev 0x01
pci32 at ppb31 bus 32
ppb32 at pci0 dev 24 function 6 VMware PCIE rev 0x01
pci33 at ppb32 bus 33
ppb33 at pci0 dev 24 function 7 VMware PCIE rev 0x01
pci34 at ppb33 bus 34
isa0 at pcib0
isadma0 at isa0
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
npx0 at isa0 

Re: sensorsd.conf(5) indicator parsing

2014-12-09 Thread David Higgs
On Tue, Dec 9, 2014 at 5:02 AM, Stuart Henderson st...@openbsd.org wrote:
 On 2014/12/08 15:04, David Higgs wrote:
 As per an earlier thread on misc@, this fixes sensorsd.conf(5)
 parsing of SENSOR_INDICATOR values. Since parsing as integers was both
 undocumented and confusing, it is no longer supported. Also, bail on
 error if the high/low values don't create a valid range.

 Low/high transitions don't make sense for these types of sensor anyway.
 That was a quick hack because the indicator sensors don't function as
 status sensors (but I didn't get as far as working out why).

 This mimics existing behavior, but still isn't very intuitive. I.e.
 low=Off:high=On will always be within user limits. Should
 indicators limits behave differently?

 Feedback is welcome.

 Specific feedback on the diff, I'm not keen on the case sensitive
 comparison (so at least use strcasecmp). But it feels to me like if
 we're changing things in this area we should fix it properly rather than
 continue the hack but using strings instead of integers. In my opinion
 the proper fix would be to treat these sensors as status sensors.


I'm looking into adding some status changes to upd(4), but it probably
isn't safe to assume that all devices provide useful status
indicators.  I don't think all of them have an obvious mapping to
status and are best left as informational, but sensorsd(8) should have
a way to add user limits / triggers regardless.

I'll look into this, thanks.

--david



last(1) crash fix

2014-12-09 Thread David Higgs
I was playing with afl a few weeks ago and found this.  I believe it is 
triggered by non-sequential timestamp records, but I didn’t dig into it or run 
afl for particularly long.  The patch below fixed all the crashes afl had found 
up to that point.

The string used doesn’t matter, ‘crmsg’ just needs to be initialized in case 
there isn’t a ‘~’ entry prior to needing to use it.

Thanks.

--david

Index: last.c
===
RCS file: /cvs/src/usr.bin/last/last.c,v
retrieving revision 1.43
diff -u -p -r1.43 last.c
--- last.c  26 Nov 2014 18:34:51 -  1.43
+++ last.c  27 Nov 2014 14:36:45 -
@@ -241,7 +241,7 @@ wtmp(void)
 {
time_t  delta, total = 0;
int timesize, wfd, snapfound = 0;
-   char*ct, *crmsg;
+   char*ct, *crmsg = invalid;
struct utmp *bp;
struct stat stb;
ssize_t bytes;




Re: sensorsd.conf(5) indicator parsing

2014-12-09 Thread David Higgs
On Tue, Dec 9, 2014 at 9:40 AM, Stuart Henderson st...@openbsd.org wrote:
 On 2014/12/09 09:36, David Higgs wrote:
 On Tue, Dec 9, 2014 at 5:02 AM, Stuart Henderson st...@openbsd.org wrote:
  On 2014/12/08 15:04, David Higgs wrote:
  As per an earlier thread on misc@, this fixes sensorsd.conf(5)
  parsing of SENSOR_INDICATOR values. Since parsing as integers was both
  undocumented and confusing, it is no longer supported. Also, bail on
  error if the high/low values don't create a valid range.
 
  Low/high transitions don't make sense for these types of sensor anyway.
  That was a quick hack because the indicator sensors don't function as
  status sensors (but I didn't get as far as working out why).
 
  This mimics existing behavior, but still isn't very intuitive. I.e.
  low=Off:high=On will always be within user limits. Should
  indicators limits behave differently?
 
  Feedback is welcome.
 
  Specific feedback on the diff, I'm not keen on the case sensitive
  comparison (so at least use strcasecmp). But it feels to me like if
  we're changing things in this area we should fix it properly rather than
  continue the hack but using strings instead of integers. In my opinion
  the proper fix would be to treat these sensors as status sensors.
 

 I'm looking into adding some status changes to upd(4), but it probably
 isn't safe to assume that all devices provide useful status
 indicators.  I don't think all of them have an obvious mapping to
 status and are best left as informational, but sensorsd(8) should have
 a way to add user limits / triggers regardless.

 I'll look into this, thanks.

 I was thinking more that it might be better for sensorsd internally
 to treat state transitions of indicator sensors like it treats
 status changes, rather than change how the sensors themselves report.
 What do you think?

Yes, that makes a lot of sense.  I still think that some of them
should have an associated status for reporting purposes (AC power loss
or mfi(4) drive status), but indicators could automatically trigger on
value changes.  User-specified high/low settings will be ignored or
rejected.  The %l (above / below / within / etc) output may need
rethinking...

--david



Re: vic0: no link on recent i386 /bsd.rd

2014-12-09 Thread David Higgs
On Tue, Dec 9, 2014 at 9:19 AM, Mark Kettenis mark.kette...@xs4all.nl wrote:
 Date: Tue, 9 Dec 2014 14:12:20 +
 From: Stuart Henderson st...@openbsd.org

 On 2014/12/09 08:37, David Higgs wrote:
  Working and non-working dmesgs from the same VM below.  Let me know if
  any more info is needed.  If this is already known, sorry for the
  noise.

 gonzalo@ has seen similar on vr(4) starting recently, but the timing
 doesn't quite match yours.

  # does not work
  OpenBSD 5.6-current (RAMDISK_CD) #555: Tue Dec  9 00:50:21 MST 2014

  # works fine
  OpenBSD 5.6-current (GENERIC) #574: Mon Dec  8 15:39:56 MST 2014

 His old (working) kernel was i386 #507 snapshot (Nov 13) and he's seeing
 problems in #572 (Dec 6 or 7th) which is a bit earlier than yours.

 Might be a different cause, of course...

 Pretty sure this one can be blamed on krw's recent changes to dhclient.


For the record, same problem with em(4) on my amd64 VM.  Fresh bsd.rd,
amd64 #613 snapshot (Dec 9), using the (U)pgrade option.  My
previously working kernel is amd64 #597 (Dec 1).



Re: upd(4) buggy firmware

2014-12-09 Thread David Higgs
On Dec 8, 2014, at 6:07 PM, Martin Pieuchot mpieuc...@nolizard.org wrote:

 On 08/12/14(Mon) 09:35, David Higgs wrote:
 On Mon, Dec 8, 2014 at 9:29 AM, Martin Pieuchot mpieuc...@nolizard.org 
 wrote:
 [...]
 Now I'd like to finish the transition that started with the import of
 upd(4) and move away from the actual 1 reportID = 1 driver model.
 Because in the end they are all sharing the same USB device actually
 represented by an uhidev(4) instance.  So I'll ride the refactoring
 needed by your buggy firmware to also change that.  Since all the
 uhidev_*_report() will be modified, we can also pass a pointer to
 the uhidev(4) device instead of one of its children.  Is it clearer?
 
 Sounds great to me.
 
 As promised, here's a second and last diff that changes the various
 uhidev_*_report() functions to provide the transfered length to the
 caller if requested.
 
 The *get* variant now also handles the first byte required for non-0
 reportID.
 
 And last but not least, it includes the hack from apcupsd to deal with
 buggy firmwares like yours.
 
 Could you try it and let me know how it goes?

Seems to work just fine on my -current VM after adding the diff below (I didn’t 
try without).  See my previous email in this thread for other comments re: your 
diff.

hw.sensors.upd0.indicator0=Off (Charging), OK
hw.sensors.upd0.indicator1=Off (Discharging), OK
hw.sensors.upd0.indicator2=On (ACPresent), OK
hw.sensors.upd0.indicator3=Off (ShutdownImminent), OK
hw.sensors.upd0.indicator4=On (BatteryPresent), OK
hw.sensors.upd0.percent0=100.00% (RemainingCapacity), OK
hw.sensors.upd0.percent1=100.00% (FullChargeCapacity), OK

--david

Index: upd.c
===
RCS file: /cvs/src/sys/dev/usb/upd.c,v
retrieving revision 1.10
diff -u -p -r1.10 upd.c
--- upd.c   12 Jul 2014 18:48:52 -  1.10
+++ upd.c   9 Dec 2014 15:39:20 -
@@ -358,8 +360,7 @@ upd_update_sensors(struct upd_softc *sc,
break;
}
 
-   /* XXX first byte which is the report id */
-   hdata = hid_get_data(buf + 1, len, sensor-hitem.loc);
+   hdata = hid_get_data(buf, len, sensor-hitem.loc);
 
sensor-ksensor.value = hdata * adjust;
sensor-ksensor.status = SENSOR_S_OK;




Re: sensorsd.conf(5) indicator parsing

2014-12-09 Thread David Higgs
On Dec 9, 2014, at 9:53 AM, David Higgs hig...@gmail.com wrote:

 On Tue, Dec 9, 2014 at 9:40 AM, Stuart Henderson st...@openbsd.org wrote:
 
 I was thinking more that it might be better for sensorsd internally
 to treat state transitions of indicator sensors like it treats
 status changes, rather than change how the sensors themselves report.
 What do you think?
 
 Yes, that makes a lot of sense.  I still think that some of them
 should have an associated status for reporting purposes (AC power loss
 or mfi(4) drive status), but indicators could automatically trigger on
 value changes.  User-specified high/low settings will be ignored or
 rejected.  The %l (above / below / within / etc) output may need
 rethinking…
 

Something like the following, maybe?

Add a new ‘rvalues’ capability for sensorsd.conf(5) to report value changes.  
While most useful for indicator and drive sensors, it can provide granular 
output for *any* sensor that changes slowly enough for sensorsd(8) debouncing 
behavior.

Also, ignore user-specified limits on indicator and drive sensors.  These types 
of sensors are not actually intervals; using them as such was confusing, 
error-prone, and undocumented.  Users should specify ‘rvalues’ with an optional 
‘command=’ to implement more useful behavior.

--david

Index: sensorsd.c
===
RCS file: /cvs/src/usr.sbin/sensorsd/sensorsd.c,v
retrieving revision 1.53
diff -u -p -r1.53 sensorsd.c
--- sensorsd.c  29 Jun 2014 00:58:45 -  1.53
+++ sensorsd.c  9 Dec 2014 23:53:34 -
@@ -50,20 +50,26 @@ struct limits_t {
enum sensor_typetype;   /* sensor type */
int numt;   /* sensor number */
int64_t last_val;
+   int64_t last_val2;
int64_t lower;  /* lower limit */
int64_t upper;  /* upper limit */
char*command;   /* failure command */
time_t  astatus_changed;
+   time_t  value_changed;
time_t  ustatus_changed;
enum sensor_status  astatus;/* last automatic status */
enum sensor_status  astatus2;
+   int last_valid; /* last value validity */
+   int last_valid2;
enum sensorsd_s_status  ustatus;/* last user-limit status */
enum sensorsd_s_status  ustatus2;
int acount; /* stat change counter */
+   int vcount; /* value change counter */
int ucount; /* stat change counter */
u_int8_tflags;  /* sensorsd limit flags */
 #define SENSORSD_L_USERLIMIT   0x0001  /* user specified limit */
 #define SENSORSD_L_ISTATUS 0x0002  /* ignore automatic status */
+#define SENSORSD_L_RVALUES 0x0004  /* report value changes */
 };
 
 struct sdlim_t {
@@ -337,6 +343,7 @@ check_sdlim(struct sdlim_t *sdlim, time_
 
TAILQ_FOREACH(limit, sdlim-limits, entries) {
if ((limit-flags  SENSORSD_L_ISTATUS) 
+   !(limit-flags  SENSORSD_L_RVALUES) 
!(limit-flags  SENSORSD_L_USERLIMIT))
continue;
 
@@ -361,6 +368,28 @@ check_sdlim(struct sdlim_t *sdlim, time_
}
}
 
+   if (limit-flags  SENSORSD_L_RVALUES) {
+   int newvalid = !(sensor.flags  SENSOR_FINVALID);
+
+   if (limit-last_val != sensor.value ||
+   limit-last_valid != newvalid) {
+   if (limit-last_val2 != sensor.value ||
+   limit-last_valid2 != newvalid) {
+   limit-last_val2 = sensor.value;
+   limit-last_valid2 = newvalid;
+   limit-vcount = 0;
+   } else if (++limit-vcount = 3) {
+   limit-last_val2 =
+   limit-last_val = sensor.value;
+   limit-last_valid2 =
+   limit-last_valid = newvalid;
+   limit-astatus2 =
+   limit-astatus = sensor.status;
+   limit-value_changed = this_check;
+   }
+   }
+   }
+
if (limit-flags  SENSORSD_L_USERLIMIT) {
enum sensorsd_s_status   newustatus;
 
@@ -422,10 +451,12 @@ report_sdlim(struct sdlim_t *sdlim, time
 
TAILQ_FOREACH(limit, sdlim-limits, entries

Re: upd(4) buggy firmware

2014-12-08 Thread David Higgs
On Sat, Dec 6, 2014 at 8:57 AM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 The ohci(4) diff is almost fine, USBD_SHORT_XFER should only be set in
 usbd_transfer_complete() so the HCD should only set the status to
 USBD_NORMAL_COMPLETION, see below.

 Concerning your broken firmware, what we should do is change the
 uhidev_*_report() function to somehow return the number of transferred
 bytes (actlen).  Since this involves calling usbd_do_request_flag() and
 update all the consumers of this API, here's a first step.

 Could you test the diff below and tell me if it still works for you?
 You'll still need your upd(4) diff.  If that works, I'll commit it and
 send a second diff to deal with your broken firmware.

Seems to work fine when patched against -stable.  (Sorry, I'd rather
not update this box to -current, unless necessary for some later
diff).

Since uhidev_set_report didn't change, why did wacom behavior need
tweaking?  I don't own this peripheral...

--david



Re: upd(4) buggy firmware

2014-12-08 Thread David Higgs
On Mon, Dec 8, 2014 at 9:29 AM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 08/12/14(Mon) 09:02, David Higgs wrote:
 On Sat, Dec 6, 2014 at 8:57 AM, Martin Pieuchot mpieuc...@nolizard.org 
 wrote:
  The ohci(4) diff is almost fine, USBD_SHORT_XFER should only be set in
  usbd_transfer_complete() so the HCD should only set the status to
  USBD_NORMAL_COMPLETION, see below.
 
  Concerning your broken firmware, what we should do is change the
  uhidev_*_report() function to somehow return the number of transferred
  bytes (actlen).  Since this involves calling usbd_do_request_flag() and
  update all the consumers of this API, here's a first step.
 
  Could you test the diff below and tell me if it still works for you?
  You'll still need your upd(4) diff.  If that works, I'll commit it and
  send a second diff to deal with your broken firmware.

 Seems to work fine when patched against -stable.  (Sorry, I'd rather
 not update this box to -current, unless necessary for some later
 diff).

 Stable should be fine.  Does this include the ohci(4) diff?

Yes, I replaced my ohci(4) tweak with your full diff, while keeping my
changes to upd(4).

 Since uhidev_set_report didn't change, why did wacom behavior need
 tweaking?  I don't own this peripheral...

 Because it was using usb_set_report() instead of uhidev_set_report() and
 doing the reportID dance by itself.

Whoops, you're right.  I missed that there was a different function prefix.

 Now I'd like to finish the transition that started with the import of
 upd(4) and move away from the actual 1 reportID = 1 driver model.
 Because in the end they are all sharing the same USB device actually
 represented by an uhidev(4) instance.  So I'll ride the refactoring
 needed by your buggy firmware to also change that.  Since all the
 uhidev_*_report() will be modified, we can also pass a pointer to
 the uhidev(4) device instead of one of its children.  Is it clearer?

Sounds great to me.

--david



sensorsd.conf(5) indicator parsing

2014-12-08 Thread David Higgs
As per an earlier thread on misc@, this fixes sensorsd.conf(5) parsing of 
SENSOR_INDICATOR values.  Since parsing as integers was both undocumented and 
confusing, it is no longer supported.  Also, bail on error if the high/low 
values don’t create a valid range.

This mimics existing behavior, but still isn't very intuitive.  I.e. 
“low=Off:high=On” will always be “within” user limits.  Should indicators 
limits behave differently?

Feedback is welcome.

--david

Index: sensorsd.c
===
RCS file: /cvs/src/usr.sbin/sensorsd/sensorsd.c,v
retrieving revision 1.53
diff -u -p -r1.53 sensorsd.c
--- sensorsd.c  29 Jun 2014 00:58:45 -  1.53
+++ sensorsd.c  8 Dec 2014 19:45:45 -
@@ -723,6 +723,8 @@ parse_config_sdlim(struct sdlim_t *sdlim
if (cgetstr(buf, high, ebuf)  0)
ebuf = NULL;
p-upper = get_val(ebuf, 1, p-type);
+   if (p-lower  p-upper)
+   errx(1, %s: incorrect sensor range, node);
if (cgetstr(buf, command, ebuf)  0)
ebuf = NULL;
if (ebuf)
@@ -749,7 +751,7 @@ get_val(char *buf, int upper, enum senso
}
 
val = strtod(buf, p);
-   if (buf == p)
+   if (buf == p  type != SENSOR_INDICATOR)
err(1, incorrect value: %s, buf);
 
switch(type) {
@@ -780,6 +782,13 @@ get_val(char *buf, int upper, enum senso
rval = val * 1000.0;
break;
case SENSOR_INDICATOR:
+   if (strcmp(buf, On) == 0)
+   rval = 1;
+   else if (strcmp(buf, Off) == 0)
+   rval = 0;
+   else
+   errx(1, incorrect value: %s, buf);
+   break;
case SENSOR_INTEGER:
case SENSOR_DRIVE:
case SENSOR_ANGLE:




Re: upd(4) buggy firmware

2014-12-08 Thread David Higgs
On Mon, Dec 8, 2014 at 6:07 PM, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 08/12/14(Mon) 09:35, David Higgs wrote:
 On Mon, Dec 8, 2014 at 9:29 AM, Martin Pieuchot mpieuc...@nolizard.org 
 wrote:
  [...]
  Now I'd like to finish the transition that started with the import of
  upd(4) and move away from the actual 1 reportID = 1 driver model.
  Because in the end they are all sharing the same USB device actually
  represented by an uhidev(4) instance.  So I'll ride the refactoring
  needed by your buggy firmware to also change that.  Since all the
  uhidev_*_report() will be modified, we can also pass a pointer to
  the uhidev(4) device instead of one of its children.  Is it clearer?

 Sounds great to me.

 As promised, here's a second and last diff that changes the various
 uhidev_*_report() functions to provide the transfered length to the
 caller if requested.

 The *get* variant now also handles the first byte required for non-0
 reportID.

 And last but not least, it includes the hack from apcupsd to deal with
 buggy firmwares like yours.

 Could you try it and let me know how it goes?


This diff doesn't apply cleanly against -stable but I believe it
should be safe to temporarily connect my UPS back to my -current VM
and test there, since it doesn't appear to touch ohci/ehci-specific
code paths.  Let me know if I'm wrong about this.

From reading the diff, though, I had a few questions and found at
least one problem.  See comments inline, possibly mangled by gmail.
I'll try to provide results tomorrow morning.

Thanks.

 Index: ucycom.c
 ===
 RCS file: /cvs/src/sys/dev/usb/ucycom.c,v
 retrieving revision 1.29
 diff -u -p -r1.29 ucycom.c
 --- ucycom.c12 Jul 2014 20:26:33 -  1.29
 +++ ucycom.c8 Dec 2014 22:54:53 -
 @@ -453,8 +453,8 @@ ucycom_param(void *addr, int portno, str
 report[2] = (baud  16)  0xff;
 report[3] = (baud  24)  0xff;
 report[4] = cfg;
 -   err = uhidev_set_report(sc-sc_hdev, UHID_FEATURE_REPORT,
 -   sc-sc_hdev.sc_report_id, report, sc-sc_flen);
 +   err = uhidev_set_report(sc-sc_hdev.sc_parent, UHID_FEATURE_REPORT,
 +   sc-sc_hdev.sc_report_id, report, sc-sc_flen, NULL);
 if (err != 0) {
 DPRINTF((ucycom_param: uhidev_set_report %d %s\n,
 err, usbd_errstr(err)));
 @@ -553,11 +553,11 @@ ucycom_set(void *addr, int portno, int r
  void
  ucycom_get_cfg(struct ucycom_softc *sc)
  {
 -   int err, cfg, baud;
 +   int cfg, baud;
 uint8_t report[5];

 -   err = uhidev_get_report(sc-sc_hdev, UHID_FEATURE_REPORT,
 -   sc-sc_hdev.sc_report_id, report, sc-sc_flen);
 +   uhidev_get_report(sc-sc_hdev.sc_parent, UHID_FEATURE_REPORT,
 +   sc-sc_hdev.sc_report_id, report, sc-sc_flen, NULL);
 cfg = report[4];
 baud = (report[3]  24) + (report[2]  16) + (report[1]  8) + 
 report[0];
 DPRINTF((ucycom_configure: device reports %d baud, %d-%c-%d (%d)\n, 
 baud,
 Index: ugold.c
 ===
 RCS file: /cvs/src/sys/dev/usb/ugold.c,v
 retrieving revision 1.6
 diff -u -p -r1.6 ugold.c
 --- ugold.c 29 Apr 2014 12:53:33 -  1.6
 +++ ugold.c 8 Dec 2014 22:54:53 -
 @@ -260,6 +260,6 @@ ugold_refresh(void *arg)
  int
  ugold_issue_cmd(struct ugold_softc *sc, uint8_t *cmd, int len)
  {
 -   return uhidev_set_report_async(sc-sc_hdev, UHID_OUTPUT_REPORT,
 -   sc-sc_hdev.sc_report_id, cmd, len);
 +   return uhidev_set_report_async(sc-sc_hdev.sc_parent,
 +   UHID_OUTPUT_REPORT, sc-sc_hdev.sc_report_id, cmd, len, NULL);
  }
 Index: uhid.c
 ===
 RCS file: /cvs/src/sys/dev/usb/uhid.c,v
 retrieving revision 1.58
 diff -u -p -r1.58 uhid.c
 --- uhid.c  12 Jul 2014 18:48:52 -  1.58
 +++ uhid.c  8 Dec 2014 22:54:53 -
 @@ -259,7 +259,6 @@ uhid_do_read(struct uhid_softc *sc, stru
  {
 int s;
 int error = 0;
 -   int extra;
 size_t length;
 u_char buffer[UHID_CHUNK];
 usbd_status err;
 @@ -267,13 +266,12 @@ uhid_do_read(struct uhid_softc *sc, stru
 DPRINTFN(1, (uhidread\n));
 if (sc-sc_state  UHID_IMMED) {
 DPRINTFN(1, (uhidread immed\n));
 -   extra = sc-sc_hdev.sc_report_id != 0;
 -   err = uhidev_get_report(sc-sc_hdev, UHID_INPUT_REPORT,
 -   sc-sc_hdev.sc_report_id, buffer,
 -   sc-sc_hdev.sc_isize + extra);
 +   err = uhidev_get_report(sc-sc_hdev.sc_parent,
 +   UHID_INPUT_REPORT, sc-sc_hdev.sc_report_id, buffer,
 +   sc-sc_hdev.sc_isize, NULL);
 if (err)
 return (EIO);
 -   return (uiomove(buffer+extra, sc-sc_hdev.sc_isize, uio));
 +   return (uiomove(buffer, sc

Re: upd(4) buggy firmware

2014-12-05 Thread David Higgs
On Dec 4, 2014, at 4:30 PM, David Higgs hig...@gmail.com wrote:

 I am trying to figure out how to handle the buggy USB firmware in my UPS (see 
 misc@ thread from last week).  With some kernel debug enabled, I see 
 usb_transfer_complete: short transfer 35 messages.  Since the 
 BatteryPresent sensor could not be read, all battery-related sensors were 
 forced into UNKNOWN state.
 
 It appears that apcupsd adjusts the expected HID report length as soon as a 
 bogus request is detected:
 http://sourceforge.net/p/apcupsd/svn/2273/tree/branches/Branch-3_14/src/drivers/usb/generic/generic-usb.c#l254
 
 The patch below handles my particular case but is probably too 
 generic/sloppy.  Is there any interest in workarounds, either like this or 
 something less terrible?

Below is an updated diff against -current, and dmesg when applied to -stable 
(no change).  On my non-virtual hardware, upd(4) connects via ohci(4), which 
didn’t report USBD_SHORT_XFER.  Also, I fixed a format string warning when 
UPD_DEBUG was enabled.

Please let me know if my diffs are still being mangled, so I can resend as 
attachments and keep searching for a solution.

Feedback is welcome.

--david



OpenBSD 5.6-stable (GENERIC) #8: Fri Dec  5 13:25:33 EST 2014
vm@vm.localdomain:/home/vm/src/sys/arch/i386/compile/GENERIC
cpu0: Geode(TM) Integrated Processor by AMD PCS (AuthenticAMD 586-class) 499 
MHz
cpu0: FPU,DE,PSE,TSC,MSR,CX8,SEP,PGE,CMOV,CFLUSH,MMX,MMXX,3DNOW2,3DNOW
real mem  = 267943936 (255MB)
avail mem = 251113472 (239MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 11/05/08, BIOS32 rev. 0 @ 0xfd088
pcibios0 at bios0: rev 2.1 @ 0xf/0x1
pcibios0: pcibios_get_intr_routing - function not supported
pcibios0: PCI IRQ Routing information unavailable.
pcibios0: PCI bus #0 is the last bus
bios0: ROM list: 0xe/0xa800
cpu0 at mainbus0: (uniprocessor)
mtrr: K6-family MTRR support (2 registers)
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 1 function 0 AMD Geode LX rev 0x33
glxsb0 at pci0 dev 1 function 2 AMD Geode LX Crypto rev 0x00: RNG AES
vr0 at pci0 dev 9 function 0 VIA VT6105M RhineIII rev 0x96: irq 10, address 
00:0d:b9:1e:60:7c
ukphy0 at vr0 phy 1: Generic IEEE 802.3u media interface, rev. 3: OUI 0x004063, 
model 0x0034
vr1 at pci0 dev 10 function 0 VIA VT6105M RhineIII rev 0x96: irq 11, address 
00:0d:b9:1e:60:7d
ukphy1 at vr1 phy 1: Generic IEEE 802.3u media interface, rev. 3: OUI 0x004063, 
model 0x0034
vr2 at pci0 dev 11 function 0 VIA VT6105M RhineIII rev 0x96: irq 15, address 
00:0d:b9:1e:60:7e
ukphy2 at vr2 phy 1: Generic IEEE 802.3u media interface, rev. 3: OUI 0x004063, 
model 0x0034
glxpcib0 at pci0 dev 15 function 0 AMD CS5536 ISA rev 0x03: rev 3, 32-bit 
3579545Hz timer, watchdog, gpio, i2c
gpio0 at glxpcib0: 32 pins
iic0 at glxpcib0
maxtmp0 at iic0 addr 0x4c: lm86
pciide0 at pci0 dev 15 function 2 AMD CS5536 IDE rev 0x01: DMA, channel 0 
wired to compatibility, channel 1 wired to compatibility
wd0 at pciide0 channel 0 drive 0: TS16GCF133
wd0: 1-sector PIO, LBA, 15296MB, 31326208 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 ignored (disabled)
ohci0 at pci0 dev 15 function 4 AMD CS5536 USB rev 0x02: irq 12, version 1.0, 
legacy support
ehci0 at pci0 dev 15 function 5 AMD CS5536 USB rev 0x02: irq 12
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 AMD EHCI root hub rev 2.00/1.00 addr 1
isa0 at glxpcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: console
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
usb1 at ohci0: USB revision 1.0
uhub1 at usb1 AMD OHCI root hub rev 1.00/1.00 addr 1
nvram: invalid checksum
uhidev0 at uhub1 port 2 configuration 1 interface 0 American Power Conversion 
Back-UPS ES 750 FW:841.I3 .D USB FW:I3 rev 1.10/1.01 addr 2
uhidev0: iclass 3/0, 146 report ids
upd0 at uhidev0
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
scsibus2 at softraid0: 256 targets
root on wd0a (295fd65258ac0a48.a) swap on wd0b dump on wd0b
clock: unknown CMOS layout


Index: ohci.c
===
RCS file: /cvs/src/sys/dev/usb/ohci.c,v
retrieving revision 1.140
diff -u -p -r1.140 ohci.c
--- ohci.c  5 Oct 2014 08:40:29 -   1.140
+++ ohci.c  5 Dec 2014 18:45:40 -
@@ -1311,6 +1311,8 @@ ohci_softintr(void *v)
 
if (cc == OHCI_CC_STALL)
xfer-status = USBD_STALLED;
+   else if (cc == OHCI_CC_DATA_UNDERRUN)
+   xfer-status = USBD_SHORT_XFER;
else
xfer-status = USBD_IOERROR;
s = splusb();
Index: upd.c
===
RCS file: /cvs/src/sys

upd(4) buggy firmware

2014-12-04 Thread David Higgs
I am trying to figure out how to handle the buggy USB firmware in my UPS (see 
misc@ thread from last week).  With some kernel debug enabled, I see 
usb_transfer_complete: short transfer 35 messages.  Since the BatteryPresent 
sensor could not be read, all battery-related sensors were forced into UNKNOWN 
state.

It appears that apcupsd adjusts the expected HID report length as soon as a 
bogus request is detected:
http://sourceforge.net/p/apcupsd/svn/2273/tree/branches/Branch-3_14/src/drivers/usb/generic/generic-usb.c#l254

The patch below handles my particular case but is probably too generic/sloppy.  
Is there any interest in workarounds, either like this or something less 
terrible?

Thanks.

--david

OpenBSD 5.6-current (GENERIC) #0: Thu Dec  4 16:24:54 EST 2014
vm@vm.localdomain:/home/vm/src/sys/arch/i386/compile/GENERIC
cpu0: Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz (GenuineIntel 686-class) 
2.40 GHz
cpu0: 
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,NXE,LONG,SSE3,SSSE3,CX16,LAHF,PERF,ITSC
real mem  = 267866112 (255MB)
avail mem = 251166720 (239MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 09/20/12, BIOS32 rev. 0 @ 0xfd780, SMBIOS 
rev. 2.4 @ 0xe0010 (364 entries)
bios0: vendor Phoenix Technologies LTD version 6.00 date 09/20/2012
bios0: VMware, Inc. VMware Virtual Platform
acpi0 at bios0: rev 2
acpi0: sleep states S0 S1 S4 S5
acpi0: tables DSDT FACP BOOT APIC MCFG SRAT HPET WAET
acpi0: wakeup devices PCI0(S3) USB_(S1) P2P0(S3) S1F0(S3) S2F0(S3) S3F0(S3) 
S4F0(S3) S5F0(S3) S6F0(S3) S7F0(S3) S8F0(S3) S9F0(S3) Z00Q(S3) Z00R(S3) 
Z00S(S3) Z00T(S3) [...]
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
cpu0: apic clock running at 65MHz
ioapic0 at mainbus0: apid 1 pa 0xfec0, version 11, 24 pins
acpimcfg0 at acpi0 addr 0xe000, bus 0-255
acpihpet0 at acpi0: 14318179 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpicpu0 at acpi0
acpibat0 at acpi0: BAT1 not present
acpibat1 at acpi0: BAT2 not present
acpiac0 at acpi0: AC unit online
acpibtn0 at acpi0: SLPB
acpibtn1 at acpi0: LID_
bios0: ROM list: 0xc/0x8000 0xc8000/0x1000 0xdc000/0x4000! 0xe/0x8000!
vmt0 at mainbus0
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 Intel 82443BX AGP rev 0x01
ppb0 at pci0 dev 1 function 0 Intel 82443BX AGP rev 0x01
pci1 at ppb0 bus 1
piixpcib0 at pci0 dev 7 function 0 Intel 82371AB PIIX4 ISA rev 0x08
pciide0 at pci0 dev 7 function 1 Intel 82371AB IDE rev 0x01: DMA, channel 0 
configured to compatibility, channel 1 configured to compatibility
wd0 at pciide0 channel 0 drive 0: VMware Virtual IDE Hard Drive
wd0: 64-sector PIO, LBA, 8192MB, 16777216 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 disabled (no drives)
piixpm0 at pci0 dev 7 function 3 Intel 82371AB Power rev 0x08: SMBus disabled
VMware VMCI rev 0x10 at pci0 dev 7 function 7 not configured
vga1 at pci0 dev 15 function 0 VMware SVGA II rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
ppb1 at pci0 dev 17 function 0 VMware PCI rev 0x02
pci2 at ppb1 bus 2
vic0 at pci2 dev 0 function 0 AMD 79c970 PCnet-PCI rev 0x10: apic 1 int 18, 
address 00:0c:29:23:6c:31
uhci0 at pci2 dev 2 function 0 VMware UHCI rev 0x00: apic 1 int 16
ehci0 at pci2 dev 3 function 0 VMware EHCI rev 0x00: apic 1 int 17
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 VMware EHCI root hub rev 2.00/1.00 addr 1
usb1 at uhci0: USB revision 1.0
uhub1 at usb1 VMware UHCI root hub rev 1.00/1.00 addr 1
ppb2 at pci0 dev 21 function 0 VMware PCIE rev 0x01
pci3 at ppb2 bus 3
ppb3 at pci0 dev 21 function 1 VMware PCIE rev 0x01
pci4 at ppb3 bus 4
ppb4 at pci0 dev 21 function 2 VMware PCIE rev 0x01
pci5 at ppb4 bus 5
ppb5 at pci0 dev 21 function 3 VMware PCIE rev 0x01
pci6 at ppb5 bus 6
ppb6 at pci0 dev 21 function 4 VMware PCIE rev 0x01
pci7 at ppb6 bus 7
ppb7 at pci0 dev 21 function 5 VMware PCIE rev 0x01
pci8 at ppb7 bus 8
ppb8 at pci0 dev 21 function 6 VMware PCIE rev 0x01
pci9 at ppb8 bus 9
ppb9 at pci0 dev 21 function 7 VMware PCIE rev 0x01
pci10 at ppb9 bus 10
ppb10 at pci0 dev 22 function 0 VMware PCIE rev 0x01
pci11 at ppb10 bus 11
ppb11 at pci0 dev 22 function 1 VMware PCIE rev 0x01
pci12 at ppb11 bus 12
ppb12 at pci0 dev 22 function 2 VMware PCIE rev 0x01
pci13 at ppb12 bus 13
ppb13 at pci0 dev 22 function 3 VMware PCIE rev 0x01
pci14 at ppb13 bus 14
ppb14 at pci0 dev 22 function 4 VMware PCIE rev 0x01
pci15 at ppb14 bus 15
ppb15 at pci0 dev 22 function 5 VMware PCIE rev 0x01
pci16 at ppb15 bus 16
ppb16 at pci0 dev 22 function 6 VMware PCIE rev 0x01
pci17 at ppb16 bus 17
ppb17 at pci0 dev 22 function 7 VMware PCIE rev 0x01
pci18 at ppb17 bus 18
ppb18 at pci0 dev 23 function 0 VMware PCIE rev 

Re: sk(4): jumbo mbufs and rxring accounting

2014-08-18 Thread David Higgs
On Mon, Aug 18, 2014 at 6:24 PM, David Gwynne da...@gwynne.id.au wrote:
 On Sun, Jul 13, 2014 at 02:01:15PM +1000, David Gwynne wrote:
 i think i'll try to find the sk at work and wire it up. its just annoying 
 cos im pretty sure its sr optics with sc connectors.

 thanks for testing.

 how's this one?


Are either of you (or anyone else) interested in one or both of my
twisted-pair sk(4) cards?  I've plugged maybe once or twice in the
last few years and maybe they can be put to better use elsewhere.  I
never saw them in want.html and never offered because I figured they
fell in the very common PCI category, but contact me off-list if
this isn't the case to help me figure out where to ship them to.

Full dmesg: http://marc.info/?l=openbsd-techm=139062896512049w=2

skc0 at pci0 dev 16 function 0 3Com 3c940 rev 0x10, Yukon (0x1): irq 9
sk0 at skc0 port A: address 00:0a:5e:5c:50:41
eephy0 at sk0 phy 0: 88E1011 Gigabit PHY, rev. 3
skc1 at pci0 dev 17 function 0 3Com 3c940 rev 0x10, Yukon (0x1): irq 10
sk1 at skc1 port A: address 00:0a:5e:65:ee:47
eephy1 at sk1 phy 0: 88E1011 Gigabit PHY, rev. 3

Thanks.

--david



strptime() fix

2014-02-13 Thread David Higgs
As of lib/libc/time/strptime.c r1.15, certain conversions will perform
calculations using the provided tm_mday value, which will frequently
produce incorrect values for tm_mday and tm_yday.  Apologies in
advance for the mangled patch.

Thanks.

--david

Compare runs of the test program below:

/* strptime_test */
#include stdio.h
#include string.h
#include time.h

int main(int argc, char **argv)
{
struct tm tm;
memset(tm, 0xff, sizeof(tm));
if (argc  2  strptime(argv[1], argv[2], tm) != NULL)
printf((%d,%d)\n, tm.tm_yday, tm.tm_mday);
else
printf(arg/parse error\n);
return 0;
}

# the two examples below should both produce (-1,-1)
./strptime_test '2014-01' '%Y-%m'
./strptime_test '2014-01' '%Y-%d'


--- strptime.c.orig 2014-02-13 13:21:12.0 -0500
+++ strptime.c 2014-02-13 13:45:44.0 -0500
@@ -594,7 +594,8 @@
  const int year = tm-tm_year + TM_YEAR_BASE;
  const int *mon_lens = mon_lengths[isleap(year)];
  if (!(fields  FIELD_TM_YDAY) 
- (fields  (FIELD_TM_MON|FIELD_TM_MDAY))) {
+ (fields  (FIELD_TM_MON|FIELD_TM_MDAY)) ==
+ ((FIELD_TM_MON|FIELD_TM_MDAY)) {
  tm-tm_yday = tm-tm_mday - 1;
  for (i = 0; i  tm-tm_mon; i++)
  tm-tm_yday += mon_lens[i];



Re: help needed from someone with an sk(4)

2014-01-24 Thread David Higgs
On Fri, Jan 24, 2014 at 4:24 AM, Henning Brauer
lists-openbsdt...@bsws.de wrote:
 * Henning Brauer lists-openbsdt...@bsws.de [2014-01-24 05:50]:
 i need this tested on an sk(4).
 I don't have that hardware at all.

 this gets rif od a slight little bit more.


Resurrected an old box, kernel compile w/ patch is underway.  Should
be able to provide feedback tomorrow.  I'm kinda new to this - do I
need to exercise forwarding, do some speed tests, or is it sufficient
to just make sure that host-based usage doesn't break?  Snapshot dmesg
below.

--david


OpenBSD 5.5-beta (GENERIC) #239: Fri Jan 24 12:06:50 MST 2014
t...@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC
cpu0: Intel Pentium III (GenuineIntel 686-class, 512KB L2 cache) 599 MHz
cpu0: 
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PSE36,MMX,FXSR,SSE,PERF
real mem  = 267927552 (255MB)
avail mem = 251641856 (239MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 10/13/00, BIOS32 rev. 0 @
0xfd790, SMBIOS rev. 2.1 @ 0xefa30 (49 entries)
bios0: vendor Intel Corp. version A11 date 10/13/2000
bios0: Dell Computer Corporation XPST600
acpi0 at bios0: rev 0
acpi0: sleep states S0 S1 S5
acpi0: tables DSDT FACP
acpi0: wakeup devices PCI0(S1) USB0(S1) UAR1(S1) KBC_(S1) MICE(S1)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpiprt0 at acpi0: bus 0 (PCI0)
acpicpu0 at acpi0: C3, C2
acpipwrres0 at acpi0: PFAN, resource for FAN1
bios0: ROM list: 0xc/0xb800 0xcb800/0x800 0xcc000/0x800
0xe/0x4000! 0xe4000/0xc000
cpu0 at mainbus0: (uniprocessor)
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 Intel 82443BX AGP rev 0x03
intelagp0 at pchb0
agp0 at intelagp0: aperture at 0xe000, size 0x1000
ppb0 at pci0 dev 1 function 0 Intel 82443BX AGP rev 0x03
pci1 at ppb0 bus 1
vga1 at pci1 dev 0 function 0 NVIDIA GeForce3 rev 0xa3
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
piixpcib0 at pci0 dev 7 function 0 Intel 82371AB PIIX4 ISA rev 0x02
pciide0 at pci0 dev 7 function 1 Intel 82371AB IDE rev 0x01: DMA,
channel 0 wired to compatibility, channel 1 wired to compatibility
wd0 at pciide0 channel 0 drive 0: Maxtor 52049H3
wd0: 16-sector PIO, LBA, 19473MB, 39882528 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 ignored (disabled)
uhci0 at pci0 dev 7 function 2 Intel 82371AB USB rev 0x01: irq 9
piixpm0 at pci0 dev 7 function 3 Intel 82371AB Power rev 0x02: SMI
iic0 at piixpm0
spdmem0 at iic0 addr 0x50: 128MB SDRAM ECC PC100CL3
spdmem1 at iic0 addr 0x51: 128MB SDRAM ECC PC100CL3
ral0 at pci0 dev 14 function 0 Ralink RT2561S rev 0x00: irq 3,
address 00:1d:7d:34:0e:ec
ral0: MAC/BBP RT2561C, RF RT2527
skc0 at pci0 dev 16 function 0 3Com 3c940 rev 0x10, Yukon (0x1): irq 9
sk0 at skc0 port A: address 00:0a:5e:5c:50:41
eephy0 at sk0 phy 0: 88E1011 Gigabit PHY, rev. 3
skc1 at pci0 dev 17 function 0 3Com 3c940 rev 0x10, Yukon (0x1): irq 10
sk1 at skc1 port A: address 00:0a:5e:65:ee:47
eephy1 at sk1 phy 0: 88E1011 Gigabit PHY, rev. 3
isa0 at piixpcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: console
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
lpt0 at isa0 port 0x378/4 irq 7
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
usb0 at uhci0: USB revision 1.0
uhub0 at usb0 Intel UHCI root hub rev 1.00/1.00 addr 1
vscsi0 at root
scsibus0 at vscsi0: 256 targets
softraid0 at root
scsibus1 at softraid0: 256 targets
root on wd0a (ffd0e9298ff269a9.a) swap on wd0b dump on wd0b



ksh globbing vs. trailing backslash [patch]

2011-02-25 Thread David Higgs
Long time user, first time patch submission.  I can send this again after tree
lock, but feedback is welcome in the meantime.

I started trying to fix PR 6006 and felt like there was progress being made
for a while.  I was pretty sure that x_file_glob function shouldn't have
stripped backslashes before lexing, which caused the unescaped backtick to
throw the error.  However, the code that checked for globbing failure would
then have to be adjusted, and I couldn't find logic to consistently predict
what expand() would return on such failure.  Getting that wrong caused tab
completion to incorrectly escape the input buffer.

Long story short I didn't fix the PR but found a minor nit that seemed safe to
fix: don't allow add_glob to process strings with a trailing backslash.

# patched code sends a bell instead of displaying matches
# unpatched code displays as below
[vm@vm obj]$ cd c_\TAB
c_ksh.o  c_sh.o   c_test.o c_ulimit.o

Thanks.

--david

Index: edit.c
===
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.34
diff -u -r1.34 edit.c
--- edit.c  20 May 2010 01:13:07 -  1.34
+++ edit.c  26 Feb 2011 01:34:36 -
@@ -355,7 +355,10 @@
if (slen  0)
return 0;

-   toglob = add_glob(str, slen);
+   if ((toglob = add_glob(str, slen)) == NULL) {
+   *wordsp = NULL;
+   return 0;
+   }

/* remove all escaping backward slashes */
escaping = 0;
@@ -455,7 +458,10 @@
if (slen  0)
return 0;

-   toglob = add_glob(str, slen);
+   if ((toglob = add_glob(str, slen)) == NULL) {
+   *wordsp = NULL;
+   return 0;
+   }

/* Convert foo* (toglob) to a pattern for future use */
pat = evalstr(toglob, DOPAT|DOTILDE);
@@ -646,6 +652,10 @@
for (s = toglob; *s; s++) {
if (*s == '\\'  s[1])
s++;
+   else if (*s == '\\'  !s[1]) {
+   afree(toglob, ATEMP);
+   return NULL;
+   }
else if (*s == '*' || *s == '[' || *s == '?' || *s == '$' ||
(s[1] == '(' /*)*/  strchr(+@!, *s)))
break;