On Tue, 2021-02-02 at 19:55 +0100, Anton Lindqvist wrote:
> On Tue, Feb 02, 2021 at 01:00:48PM +0100, Marcus Glocker wrote:
> > On Tue, Feb 02, 2021 at 08:23:29AM +0100, Anton Lindqvist wrote:
> > 
> > > On Sat, Jan 30, 2021 at 01:18:07PM +0200, Ville Valkonen wrote:
> > > > On Sat, 2021-01-30 at 08:36 +0100, Anton Lindqvist wrote:
> > > > > On Fri, Jan 29, 2021 at 10:15:05PM +0200, Ville Valkonen
> > > > > wrote:
> > > > > > Hi,
> > > > > > 
> > > > > > I have a bit oldish Logitech M705 mouse, bought around
> > > > > > 2010-2011.
> > > > > > Regarding the dmesg (on below) I can see it gets attached
> > > > > > correctly
> > > > > > to
> > > > > > uhiddp0 but doesn't report battery levels. Here's the line
> > > > > > from
> > > > > > dmesg:
> > > > > > uhidpp0 at uhidev2 device 1 mouse "M705" serial xx-xx-x-xx,
> > > > > > device
> > > > > > 2 keyboard "K750" serial xx-xx-xx-xx.
> > > > > > And corresponding sysctl values:
> > > > > > hw.sensors.uhidpp0.raw0=unknown (battery levels)
> > > > > > hw.sensors.uhidpp0.raw1=unknown (battery levels)
> > > > > > hw.sensors.uhidpp0.percent0=unknown (battery level)
> > > > > > hw.sensors.uhidpp0.percent1=unknown (battery level)
> > > > > > 
> > > > > > Not sure if censoring of serial has any value, though.
> > > > > 
> > > > > Glad to see it attaches fine to a receiver with more than one
> > > > > device
> > > > > paired. I only have one device myself and have therefore
> > > > > never been
> > > > > enable to verify this.
> > > > > 
> > > > > Could you enable UHIDPP_DEBUG and send me the output?
> > > > > 
> > > > > > On Ubuntu battery levels are detected correctly so I could
> > > > > > probably
> > > > > > take a USB dump with Wireshark and compare the differences.
> > > > > 
> > > > > Taking a USB dump on your Linux machine would be very
> > > > > helpful.
> > > > 
> > > > Hi,
> > > > 
> > > > Yes. Also remembered that you were mentioning about the debug
> > > > flag but
> > > > completely forgot that while testing. Then just before going to
> > > > sleep
> > > > recalled the debug flag. Here are the results with debug
> > > > enabled:
> > > > <dmesg_debug>
> > > > uhidev0 at uhub0 port 1 configuration 1 interface 0 "Logitech
> > > > USB Receiver" rev 2.00/12.10 addr 3
> > > > uhidev0: iclass 3/1
> > > > ukbd0 at uhidev0: 8 variable keys, 6 key codes
> > > > wskbd1 at ukbd0 mux 1
> > > > wskbd1: connecting to wsdisplay0
> > > > uhidev1 at uhub0 port 1 configuration 1 interface 1 "Logitech
> > > > USB Receiver" rev 2.00/12.10 addr 3
> > > > uhidev1: iclass 3/1, 8 report ids
> > > > ums0 at uhidev1 reportid 2: 16 buttons, Z and W dir
> > > > wsmouse2 at ums0 mux 0
> > > > uhid0 at uhidev1 reportid 3: input=4, output=0, feature=0
> > > > uhid1 at uhidev1 reportid 4: input=1, output=0, feature=0
> > > > uhid2 at uhidev1 reportid 8: input=1, output=0, feature=0
> > > > uhidev2 at uhub0 port 1 configuration 1 interface 2 "Logitech
> > > > USB Receiver" rev 2.00/12.10 addr 3
> > > > uhidev2: iclass 3/0, 33 report ids
> > > > uhidpp0 at uhidev2hidpp_send_report: 10 ff 83 b5 [30 00 00]
> > > > uhidpp_intr: 11 ff 83 b5 [30 c4 b4 96 9e 04 00 00 00 01 00 00
> > > > 00 00 00 00]
> > > > hidpp_send_report: 10 ff 83 b5 [20 00 00]
> > > > uhidpp_intr: 11 ff 83 b5 [20 09 08 10 1b 04 00 02 06 00 00 00
> > > > 00 00 00 00]
> > > > hidpp_send_report: 10 ff 83 b5 [40 00 00]
> > > > uhidpp_intr: 11 ff 83 b5 [40 04 4d 37 30 35 00 00 00 00 00 00
> > > > 00 00 00 00]
> > > >  device 1 mouse "M705" serial xx-xx-xx-9ehidpp_send_report: 10
> > > > ff 83 b5 [31 00 00]
> > > > uhidpp_intr: 11 ff 83 b5 [31 8d 37 6a 6f 1a 40 00 00 03 00 00
> > > > 00 00 00 00]
> > > > hidpp_send_report: 10 ff 83 b5 [21 00 00]
> > > > uhidpp_intr: 11 ff 83 b5 [21 08 14 40 02 04 00 01 07 00 00 00
> > > > 00 00 00 00]
> > > > hidpp_send_report: 10 ff 83 b5 [41 00 00]
> > > > uhidpp_intr: 11 ff 83 b5 [41 04 4b 37 35 30 00 00 00 00 00 00
> > > > 00 00 00 00]
> > > > , device 2 keyboard "K750" serial xx-xx-xx-6fhidpp_send_report:
> > > > 10 ff 83 b5 [32 00 00]
> > > > uhidpp_intr: 10 ff 8f 83 [b5 03 00]
> > > > hidpp_send_report: 10 ff 83 b5 [33 00 00]
> > > > uhidpp_intr: 10 ff 8f 83 [b5 03 00]
> > > > hidpp_send_report: 10 ff 83 b5 [34 00 00]
> > > > uhidpp_intr: 10 ff 8f 83 [b5 03 00]
> > > > hidpp_send_report: 10 ff 83 b5 [35 00 00]
> > > > uhidpp_intr: 10 ff 8f 83 [b5 03 00]
> > > > hidpp_send_report: 10 ff 80 00 [10 09 00]
> > > > uhidpp_intr: 10 ff 80 00 [00 00 00]
> > > > </dmesg_debug>
> > > > 
> > > > That's when the mouse was off. When I switched on the mouse
> > > > kernel
> > > > panicked. I couldn't break into DDB or alternatively failed to
> > > > type
> > > > correct commands blindly. Eventually had to shutdown the system
> > > > by
> > > > pressing the power button. Picture of the panic is here:
> > > > https://imgur.com/a/QRAD5v1
> > > 
> > > Thanks for the report. Updated diff which should fix the panic:
> > > 
> > > * Fix a bug in uhidpp_is_notification() causing notifications to
> > > be
> > >   detected as responses
> > > 
> > > * Delay installation of sensors
> > > 
> > > * Enable uhidpp on all architectures
> > > 
> > > From the panic, I can see that your device only supports HID++
> > > 1.0.
> > > Querying the battery status works a bit differently compared to
> > > HID++
> > > 2.0. I don't have a 1.0 device but can probably give this a try
> > > if
> > > you're willing to try out future diffs.
> > > 
> > > However, it would ease development by getting this in and
> > > continue
> > > development in tree. Anyone willing to ok?
> > 
> > The reason why I'm currently reluctant to ok this is because of the
> > uhidev_set_intr() part which you introduce with this diff, and I
> > don't   
> > fully understand.  I can understand that for this device you seem
> > to
> > have the need to state commands already in the attach code.
> > 
> > But is sc_subdevs[repid] really only used for the interrupt
> > handler?
> > Shouldn't it be more generically called something like
> > uhidev_set_repid, or uhidev_set_subdev or something like that?
> 
> That's a fair point. How about uhidev_set_report_dev?
> 
> diff --git share/man/man4/Makefile share/man/man4/Makefile
> index 70e62135237..22db50677db 100644
> --- share/man/man4/Makefile
> +++ share/man/man4/Makefile
> @@ -83,8 +83,8 @@ MAN=  aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 acrtc.4 \
>         txp.4 txphy.4 uaudio.4 uark.4 uath.4 ubcmtp.4 uberry.4 ubsa.4
> \
>         ubsec.4 ucom.4 uchcom.4 ucrcom.4 ucycom.4 ukspan.4 uslhcom.4
> \
>         udav.4 udcf.4 udl.4 udp.4 udsbr.4 \
> -       uftdi.4 ugen.4 ugl.4 ugold.4 uguru.4 uhci.4 uhid.4 uhidev.4
> uipaq.4 \
> -       ujoy.4 uk.4 ukbd.4 \
> +       uftdi.4 ugen.4 ugl.4 ugold.4 uguru.4 uhci.4 uhid.4 uhidev.4
> uhidpp.4 \
> +       uipaq.4 ujoy.4 uk.4 ukbd.4 \
>         ukphy.4 ulpt.4 umass.4 umb.4 umbg.4 umcs.4 umct.4 umidi.4
> umodem.4 \
>         ums.4 umsm.4 umstc.4 umt.4 unix.4 uonerng.4 uow.4 uoaklux.4
> uoakrh.4 \
>         uoakv.4 upd.4 upgt.4 upl.4 uplcom.4 ural.4 ure.4 url.4
> urlphy.4 \
> diff --git share/man/man4/uhidev.4 share/man/man4/uhidev.4
> index 06911ddef29..aa1efbea710 100644
> --- share/man/man4/uhidev.4
> +++ share/man/man4/uhidev.4
> @@ -40,6 +40,7 @@
>  .Cd "ucycom*  at uhidev?"
>  .Cd "ugold*   at uhidev?"
>  .Cd "uhid*    at uhidev?"
> +.Cd "uhidpp*  at uhidev?"
>  .Cd "ujoy*    at uhidev?"
>  .Cd "ukbd*    at uhidev?"
>  .Cd "ums*     at uhidev?"
> @@ -74,6 +75,7 @@ only dispatches data to them based on the report
> id.
>  .Xr ucycom 4 ,
>  .Xr ugold 4 ,
>  .Xr uhid 4 ,
> +.Xr uhidpp 4 ,
>  .Xr ujoy 4 ,
>  .Xr ukbd 4 ,
>  .Xr ums 4 ,
> diff --git share/man/man4/uhidpp.4 share/man/man4/uhidpp.4
> new file mode 100644
> index 00000000000..4c78380c35b
> --- /dev/null
> +++ share/man/man4/uhidpp.4
> @@ -0,0 +1,48 @@
> +.\"    $OpenBSD$
> +.\"
> +.\" Copyright (c) 2021 Anton Lindqvsit <[email protected]>
> +.\"
> +.\" Permission to use, copy, modify, and distribute this software
> for any
> +.\" purpose with or without fee is hereby granted, provided that the
> above
> +.\" copyright notice and this permission notice appear in all
> copies.
> +.\"
> +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> WARRANTIES
> +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> LIABLE FOR
> +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> DAMAGES
> +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> IN AN
> +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> OUT OF
> +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> +.\"
> +.Dd $Mdocdate$
> +.Dt UHIDPP 4
> +.Os
> +.Sh NAME
> +.Nm uhidpp
> +.Nd Logitech HID++ devices
> +.Sh SYNOPSIS
> +.Cd "uhidpp* at uhidev?"
> +.Sh DESCRIPTION
> +The
> +.Nm
> +driver provides support for Logitech HID++ devices.
> +It exposes a collection of battery sensor values which are made
> available
> +through the
> +.Xr sysctl 8
> +interface.
> +.Sh SEE ALSO
> +.Xr intro 4 ,
> +.Xr uhidev 4 ,
> +.Xr usb 4 ,
> +.Xr sensorsd 8 ,
> +.Xr sysctl 8
> +.Sh HISTORY
> +The
> +.Nm
> +driver first appeared in
> +.Ox 6.9 .
> +.Sh AUTHORS
> +The
> +.Nm
> +driver was written by
> +.An Anton Lindqvist Aq Mt [email protected] .
> diff --git share/man/man4/usb.4 share/man/man4/usb.4
> index 8b9e3ffdc3c..245d01cdef4 100644
> --- share/man/man4/usb.4
> +++ share/man/man4/usb.4
> @@ -255,6 +255,8 @@ TEMPer gold HID thermometer and hygrometer
>  Generic driver for Human Interface Devices
>  .It Xr uhidev 4
>  Base driver for all Human Interface Devices
> +.It Xr uhidpp 4
> +Logitech HID++ devices
>  .It Xr ujoy 4
>  USB joysticks/gamecontrollers
>  .It Xr ukbd 4
> diff --git sys/arch/alpha/conf/GENERIC sys/arch/alpha/conf/GENERIC
> index 05953f8e7cb..c789e5dacad 100644
> --- sys/arch/alpha/conf/GENERIC
> +++ sys/arch/alpha/conf/GENERIC
> @@ -108,6 +108,7 @@ ucom*       at uslhcom?
>  uhid*  at uhidev?                      # USB generic HID support
>  fido*  at uhidev?                      # FIDO/U2F security key
> support
>  ujoy*  at uhidev?                      # USB joystick/gamecontroller
> support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?                      # USB Power Devices sensors
>  aue*   at uhub?                        # ADMtek AN986 Pegasus
> Ethernet
>  #atu*  at uhub?                        # Atmel AT76c50x based
> 802.11b
> diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
> index ffa1b4a497c..f6c62eee450 100644
> --- sys/arch/amd64/conf/GENERIC
> +++ sys/arch/amd64/conf/GENERIC
> @@ -287,6 +287,7 @@ ucom*       at uslhcom?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  umstc* at uhidev?              # Microsoft Surface Type Cover
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
> diff --git sys/arch/arm64/conf/GENERIC sys/arch/arm64/conf/GENERIC
> index adefc8ffea9..ba8efb20919 100644
> --- sys/arch/arm64/conf/GENERIC
> +++ sys/arch/arm64/conf/GENERIC
> @@ -370,6 +370,7 @@ ucom*               at uslhcom?
>  uhid*          at uhidev?              # USB generic HID support
>  fido*          at uhidev?              # FIDO/U2F security key
> support
>  ujoy*          at uhidev?              # USB joystick/gamecontroller
> support
> +uhidpp*                at uhidev?              # Logitech HID++
> Devices
>  upd*           at uhidev?              # USB Power Devices sensors
>  aue*           at uhub?                # ADMtek AN986 Pegasus
> Ethernet
>  atu*           at uhub?                # Atmel AT76c50x based
> 802.11b
> diff --git sys/arch/armv7/conf/GENERIC sys/arch/armv7/conf/GENERIC
> index 13124411dc1..b3c146ef498 100644
> --- sys/arch/armv7/conf/GENERIC
> +++ sys/arch/armv7/conf/GENERIC
> @@ -322,6 +322,7 @@ ucom*       at uslhcom?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
>  atu*   at uhub?                # Atmel AT76c50x based 802.11b
> diff --git sys/arch/hppa/conf/GENERIC sys/arch/hppa/conf/GENERIC
> index d95e5a8977b..f27cb2a477e 100644
> --- sys/arch/hppa/conf/GENERIC
> +++ sys/arch/hppa/conf/GENERIC
> @@ -112,6 +112,7 @@ wskbd*      at ukbd? mux 1
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
>  url*   at uhub?                # Realtek RTL8150L based adapters
> diff --git sys/arch/i386/conf/GENERIC sys/arch/i386/conf/GENERIC
> index c167a2f8011..b1900cffd11 100644
> --- sys/arch/i386/conf/GENERIC
> +++ sys/arch/i386/conf/GENERIC
> @@ -285,6 +285,7 @@ ucom*       at uticom?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
>  atu*   at uhub?                # Atmel AT76c50x based 802.11b
> diff --git sys/arch/landisk/conf/GENERIC
> sys/arch/landisk/conf/GENERIC
> index 120aa0a108d..53b42e1cdf5 100644
> --- sys/arch/landisk/conf/GENERIC
> +++ sys/arch/landisk/conf/GENERIC
> @@ -138,6 +138,7 @@ ucom*       at uslhcom?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
>  atu*   at uhub?                # Atmel AT76c50x based 802.11b
> diff --git sys/arch/loongson/conf/GENERIC
> sys/arch/loongson/conf/GENERIC
> index 4e8d826142b..36d779b724a 100644
> --- sys/arch/loongson/conf/GENERIC
> +++ sys/arch/loongson/conf/GENERIC
> @@ -165,6 +165,7 @@ ucom*               at uslhcom?
>  uhid*          at uhidev?      # USB generic HID support
>  fido*          at uhidev?      # FIDO/U2F security key support
>  ujoy*          at uhidev?      # USB joystick/gamecontroller support
> +uhidpp*                at uhidev?      # Logitech HID++ Devices
>  upd*           at uhidev?      # USB Power Devices sensors
>  atu*           at uhub?        # Atmel AT76c50x based 802.11b
>  aue*           at uhub?        # ADMtek AN986 Pegasus Ethernet  
> diff --git sys/arch/macppc/conf/GENERIC sys/arch/macppc/conf/GENERIC
> index 46cd7397286..e7ee6cc0429 100644
> --- sys/arch/macppc/conf/GENERIC
> +++ sys/arch/macppc/conf/GENERIC
> @@ -261,6 +261,7 @@ ucom*       at uslhcom?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
>  atu*   at uhub?                # Atmel AT76c50x based 802.11b
> diff --git sys/arch/octeon/conf/GENERIC sys/arch/octeon/conf/GENERIC
> index e5f407d7e9a..a3aa720b4f2 100644
> --- sys/arch/octeon/conf/GENERIC
> +++ sys/arch/octeon/conf/GENERIC
> @@ -157,6 +157,7 @@ ucom*               at uslhcom?
>  uhid*          at uhidev?      # USB generic HID support
>  fido*          at uhidev?      # FIDO/U2F security key support
>  ujoy*          at uhidev?      # USB joystick/gamecontroller support
> +uhidpp*                at uhidev?      # Logitech HID++ Devices
>  upd*           at uhidev?      # USB Power Devices sensors
>  aue*           at uhub?        # ADMtek AN986 Pegasus Ethernet
>  atu*           at uhub?        # Atmel AT76c50x based 802.11b
> diff --git sys/arch/powerpc64/conf/GENERIC
> sys/arch/powerpc64/conf/GENERIC
> index cba5f59f2cf..144cc41dbeb 100644
> --- sys/arch/powerpc64/conf/GENERIC
> +++ sys/arch/powerpc64/conf/GENERIC
> @@ -128,6 +128,7 @@ ucom*       at uslhcom?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  umstc* at uhidev?              # Microsoft Surface Type Cover
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
> diff --git sys/arch/sgi/conf/GENERIC-IP27 sys/arch/sgi/conf/GENERIC-
> IP27
> index 889a921dd8f..1d47d94cf0d 100644
> --- sys/arch/sgi/conf/GENERIC-IP27
> +++ sys/arch/sgi/conf/GENERIC-IP27
> @@ -129,6 +129,7 @@ ucom*               at uslhcom?
>  uhid*          at uhidev?      # USB generic HID support
>  fido*          at uhidev?      # FIDO/U2F security key support
>  ujoy*          at uhidev?      # USB joystick/gamecontroller support
> +uhidpp*                at uhidev?      # Logitech HID++ Devices
>  atu*           at uhub?        # Atmel AT76c50x based 802.11b
>  aue*           at uhub?        # ADMtek AN986 Pegasus Ethernet  
>  axe*           at uhub?        # ASIX Electronics AX88172 USB
> Ethernet
> diff --git sys/arch/sgi/conf/GENERIC-IP30 sys/arch/sgi/conf/GENERIC-
> IP30
> index bd90d34945b..f09f274918e 100644
> --- sys/arch/sgi/conf/GENERIC-IP30
> +++ sys/arch/sgi/conf/GENERIC-IP30
> @@ -120,6 +120,7 @@ ucom*               at uslhcom?
>  uhid*          at uhidev?      # USB generic HID support
>  fido*          at uhidev?      # FIDO/U2F security key support
>  ujoy*          at uhidev?      # USB joystick/gamecontroller support
> +uhidpp*                at uhidev?      # Logitech HID++ Devices
>  atu*           at uhub?        # Atmel AT76c50x based 802.11b
>  aue*           at uhub?        # ADMtek AN986 Pegasus Ethernet  
>  axe*           at uhub?        # ASIX Electronics AX88172 USB
> Ethernet
> diff --git sys/arch/sgi/conf/GENERIC-IP32 sys/arch/sgi/conf/GENERIC-
> IP32
> index d4c0d64019a..4ccab12f171 100644
> --- sys/arch/sgi/conf/GENERIC-IP32
> +++ sys/arch/sgi/conf/GENERIC-IP32
> @@ -112,6 +112,7 @@ ucom*               at uslhcom?
>  uhid*          at uhidev?      # USB generic HID support
>  fido*          at uhidev?      # FIDO/U2F security key support
>  ujoy*          at uhidev?      # USB joystick/gamecontroller support
> +uhidpp*                at uhidev?      # Logitech HID++ Devices
>  atu*           at uhub?        # Atmel AT76c50x based 802.11b
>  aue*           at uhub?        # ADMtek AN986 Pegasus Ethernet  
>  axe*           at uhub?        # ASIX Electronics AX88172 USB
> Ethernet
> diff --git sys/arch/sparc64/conf/GENERIC
> sys/arch/sparc64/conf/GENERIC
> index e29faa8181a..416cad7bd4b 100644
> --- sys/arch/sparc64/conf/GENERIC
> +++ sys/arch/sparc64/conf/GENERIC
> @@ -225,6 +225,7 @@ ucom*       at umsm?
>  uhid*  at uhidev?              # USB generic HID support
>  fido*  at uhidev?              # FIDO/U2F security key support
>  ujoy*  at uhidev?              # USB joystick/gamecontroller support
> +uhidpp*        at uhidev?              # Logitech HID++ Devices
>  upd*   at uhidev?              # USB Power Devices sensors
>  aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
>  atu*   at uhub?                # Atmel AT76c50x based 802.11b
> diff --git sys/dev/usb/files.usb sys/dev/usb/files.usb
> index ff94bf8765b..35e533ab290 100644
> --- sys/dev/usb/files.usb
> +++ sys/dev/usb/files.usb
> @@ -483,3 +483,8 @@
> file        dev/usb/if_bwfm_usb.c           bwfm_usb
>  device umstc: hid
>  attach umstc at uhidbus
>  file   dev/usb/umstc.c                 umstc
> +
> +# Logitech HID++ Devices
> +device uhidpp: hid
> +attach uhidpp at uhidbus
> +file   dev/usb/uhidpp.c                uhidpp
> diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
> index 16f440714c1..ab403483182 100644
> --- sys/dev/usb/uhidev.c
> +++ sys/dev/usb/uhidev.c
> @@ -256,8 +256,13 @@ uhidev_attach(struct device *parent, struct
> device *self, void *aux)
>         /* Look for a driver claiming all report IDs first. */
>         dev = config_found_sm(self, &uha, NULL, uhidevsubmatch);
>         if (dev != NULL) {
> -               for (repid = 0; repid < nrepid; repid++)
> -                       sc->sc_subdevs[repid] = (struct uhidev *)dev;
> +               for (repid = 0; repid < nrepid; repid++) {
> +                       /*
> +                        * Could already be assigned by
> uhidev_set_report_dev().
> +                        */
> +                       if (sc->sc_subdevs[repid] == NULL)
> +                               sc->sc_subdevs[repid] = (struct
> uhidev *)dev;
> +               }
>                 return;
>         }
>  
> @@ -270,7 +275,9 @@ uhidev_attach(struct device *parent, struct
> device *self, void *aux)
>  
>                 uha.reportid = repid;
>                 dev = config_found_sm(self, &uha, uhidevprint,
> uhidevsubmatch);
> -               sc->sc_subdevs[repid] = (struct uhidev *)dev;
> +               /* Could already be assigned by
> uhidev_set_report_dev(). */
> +               if (sc->sc_subdevs[repid] == NULL)
> +                       sc->sc_subdevs[repid] = (struct uhidev *)dev;
>         }
>  }
>  
> @@ -992,3 +999,15 @@ uhidev_clear_iface_eps(struct uhidev_softc *sc,
> struct usbd_interface *iface)
>  bad:
>         printf("%s: clear endpoints failed!\n", __func__);
>  }
> +
> +int
> +uhidev_set_report_dev(struct uhidev_softc *sc, struct uhidev *dev,
> int repid)
> +{
> +       if ((dev->sc_state & UHIDEV_OPEN) == 0)
> +               return ENODEV;
> +       if (repid >= sc->sc_nrepid)
> +               return EINVAL;
> +
> +       sc->sc_subdevs[repid] = dev;
> +       return 0;
> +}
> diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
> index 16657f1e712..bb6f64c65f0 100644
> --- sys/dev/usb/uhidev.h
> +++ sys/dev/usb/uhidev.h
> @@ -95,3 +95,4 @@ int uhidev_get_report(struct uhidev_softc *, int,
> int, void *, int);
>  int uhidev_get_report_async(struct uhidev_softc *, int, int, void *,
> int,
>      void *, void (*)(void *, int, void *, int));
>  usbd_status uhidev_write(struct uhidev_softc *, void *, int);
> +int uhidev_set_report_dev(struct uhidev_softc *, struct uhidev *,
> int);
> diff --git sys/dev/usb/uhidpp.c sys/dev/usb/uhidpp.c
> new file mode 100644
> index 00000000000..942b4d45d4f
> --- /dev/null
> +++ sys/dev/usb/uhidpp.c
> @@ -0,0 +1,1054 @@
> +/*     $OpenBSD$       */
> +
> +/*
> + * Copyright (c) 2021 Anton Lindqvist <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for
> any
> + * purpose with or without fee is hereby granted, provided that the
> above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/kernel.h>
> +#include <sys/device.h>
> +#include <sys/mutex.h>
> +#include <sys/sensors.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbhid.h>
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdevs.h>
> +#include <dev/usb/uhidev.h>
> +
> +/* #define UHIDPP_DEBUG */
> +#ifdef UHIDPP_DEBUG
> +
> +#define DPRINTF(x...) do
> {                                             \
> +       if
> (uhidpp_debug)                                               \
> +               printf(x);                                           
>    \
> +} while (0)
> +
> +#define DREPORT(prefix, repid, buf, len) do
> {                          \
> +       if
> (uhidpp_debug)                                               \
> +               uhidd_dump_report((prefix), (repid), (buf),
> (len));     \
> +} while (0)
> +
> +void uhidd_dump_report(const char *, uint8_t, const unsigned char *,
> u_int);
> +
> +int uhidpp_debug = 1;
> +
> +#else
> +
> +#define DPRINTF(x...)
> +#define DREPORT(prefix, repid, buf, len)
> +
> +#endif
> +
> +#define HIDPP_LINK_STATUS(x)   ((x) & (1 << 7))
> +
> +#define HIDPP_REPORT_ID_SHORT                  0x10
> +#define HIDPP_REPORT_ID_LONG                   0x11
> +
> +/*
> + * Length of reports. Note that the effective length is always +1 as
> + * uhidev_set_report() prepends the report ID.
> + */
> +#define HIDPP_REPORT_SHORT_LENGTH              (7 - 1)
> +#define HIDPP_REPORT_LONG_LENGTH               (20 - 1)
> +
> +/*
> + * Maximum number of allowed parameters for reports. Note, the
> parameters always
> + * starts at offset 3 for both RAP and FAP reports.
> + */
> +#define
> HIDPP_REPORT_SHORT_PARAMS_MAX          (HIDPP_REPORT_SHORT_LENGTH -
> 3)
> +#define
> HIDPP_REPORT_LONG_PARAMS_MAX           (HIDPP_REPORT_LONG_LENGTH - 3)
> +
> +#define HIDPP_DEVICE_ID_RECEIVER               0xff
> +
> +#define HIDPP_FEAT_ROOT_IDX                    0x00
> +#define HIDPP_FEAT_ROOT_PING_FUNC              0x01
> +#define HIDPP_FEAT_ROOT_PING_DATA              0x5a
> +
> +#define HIDPP_SET_REGISTER                     0x80
> +#define HIDPP_GET_REGISTER                     0x81
> +#define HIDPP_SET_LONG_REGISTER                        0x82
> +#define HIDPP_GET_LONG_REGISTER                        0x83
> +
> +#define HIDPP_REG_ENABLE_REPORTS               0x00
> +#define HIDPP_REG_PAIRING_INFORMATION          0xb5
> +
> +#define HIDPP_NOTIF_DEVICE_BATTERY_STATUS      (1 << 4)
> +#define HIDPP_NOTIF_RECEIVER_WIRELESS          (1 << 0)
> +#define HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT  (1 << 3)
> +
> +/* HID++ 1.0 error codes. */
> +#define HIDPP_ERROR                            0x8f
> +#define HIDPP_ERROR_SUCCESS                    0x00
> +#define HIDPP_ERROR_INVALID_SUBID              0x01
> +#define HIDPP_ERROR_INVALID_ADRESS             0x02
> +#define HIDPP_ERROR_INVALID_VALUE              0x03
> +#define HIDPP_ERROR_CONNECT_FAIL               0x04
> +#define HIDPP_ERROR_TOO_MANY_DEVICES           0x05
> +#define HIDPP_ERROR_ALREADY_EXISTS             0x06
> +#define HIDPP_ERROR_BUSY                       0x07
> +#define HIDPP_ERROR_UNKNOWN_DEVICE             0x08
> +#define HIDPP_ERROR_RESOURCE_ERROR             0x09
> +#define HIDPP_ERROR_REQUEST_UNAVAILABLE                0x0a
> +#define HIDPP_ERROR_INVALID_PARAM_VALUE                0x0b
> +#define HIDPP_ERROR_WRONG_PIN_CODE             0x0c
> +
> +/*
> + * The software ID is added to feature access reports (FAP) and used
> to
> + * distinguish responses from notifications. Note, the software ID
> must be
> + * greater than zero which is reserved for notifications.
> + */
> +#define HIDPP_SOFTWARE_ID                      0x01
> +#define HIDPP_SOFTWARE_ID_MASK                 0x0f
> +#define HIDPP_SOFTWARE_ID_LEN                  4
> +
> +#define HIDPP20_FEAT_ROOT_IDX                  0x00
> +#define HIDPP20_FEAT_ROOT_GET_FEATURE_FUNC     0x00
> +
> +#define HIDPP20_FEAT_BATTERY_IDX               0x1000
> +#define HIDPP20_FEAT_BATTERY_LEVEL_FUNC                0x0000
> +#define HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC   0x0001
> +
> +/* HID++ 2.0 error codes. */
> +#define HIDPP20_ERROR                          0xff
> +#define HIDPP20_ERROR_NO_ERROR                 0x00
> +#define HIDPP20_ERROR_UNKNOWN                  0x01
> +#define HIDPP20_ERROR_INVALID_ARGUMENT         0x02
> +#define HIDPP20_ERROR_OUT_OF_RANGE             0x03
> +#define HIDPP20_ERROR_HARDWARE_ERROR           0x04
> +#define HIDPP20_ERROR_LOGITECH_INTERNAL                0x05
> +#define HIDPP20_ERROR_INVALID_FEATURE_INDEX    0x06
> +#define HIDPP20_ERROR_INVALID_FUNCTION_ID      0x07
> +#define HIDPP20_ERROR_BUSY                     0x08
> +#define HIDPP20_ERROR_UNSUPPORTED              0x09
> +
> +/*
> + * Sentinels used for interrupt response synchronization. The values
> must be
> + * disjoint from existing report IDs.
> + */
> +#define UHIDPP_RESP_NONE                       0
> +#define UHIDPP_RESP_WAIT                       1
> +#define UHIDPP_RESP_ERROR                      2
> +
> +/* Maximum number of devices associated with a single receiver. */
> +#define UHIDPP_NDEVICES                                6
> +
> +/* Maximum number of pending notifications. */
> +#define UHIDPP_NNOTIFICATIONS                  4
> +
> +/* Number of sensors per paired device. */
> +#define UHIDPP_NSENSORS                                2
> +
> +/* Feature access report used by the HID++ 2.0 (and greater)
> protocol. */
> +struct fap {
> +       uint8_t feature_index;
> +       uint8_t funcindex_clientid;
> +       uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX];
> +};
> +
> +/*
> + * Register access report used by the HID++ 1.0 protocol. Receivers
> always uses
> + * this type of report.
> + */
> +struct rap {
> +       uint8_t sub_id;
> +       uint8_t reg_address;
> +       uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX];
> +};
> +
> +struct uhidpp_report {
> +       uint8_t device_id;
> +       union {
> +               struct fap fap;
> +               struct rap rap;
> +       };
> +} __packed;
> +
> +struct uhidpp_notification {
> +       struct uhidpp_report n_rep;
> +       unsigned int n_id;
> +};
> +
> +struct uhidpp_device {
> +       uint8_t d_id;
> +       uint8_t d_connected;
> +       struct {
> +               struct ksensor b_sens[UHIDPP_NSENSORS];
> +               uint8_t b_feature_idx;
> +               uint8_t b_level;
> +               uint8_t b_next_level;
> +               uint8_t b_status;
> +               uint8_t b_nlevels;
> +       } d_battery;
> +};
> +
> +/*
> + * Locking:
> + *     [m]     sc_mtx
> + */
> +struct uhidpp_softc {
> +       struct uhidev sc_hdev;
> +       struct usbd_device *sc_udev;
> +
> +       struct mutex sc_mtx;
> +
> +       struct uhidpp_device sc_devices[UHIDPP_NDEVICES];
> +                                       /* [m] connected devices */
> +
> +       struct uhidpp_notification
> sc_notifications[UHIDPP_NNOTIFICATIONS];
> +                                       /* [m] pending notifications
> */
> +
> +       struct usb_task sc_task;        /* [m] notification task */
> +
> +       struct ksensordev sc_sensdev;   /* [m] */
> +       struct sensor_task *sc_senstsk; /* [m] */
> +
> +       struct uhidpp_report *sc_req;   /* [m] synchronous request
> buffer */
> +       struct uhidpp_report *sc_resp;  /* [m] synchronous response
> buffer */
> +       u_int sc_resp_state;            /* [m] synchronous response
> state */
> +
> +};
> +
> +int uhidpp_match(struct device *, void *, void *);
> +void uhidpp_attach(struct device *, struct device *, void *);
> +int uhidpp_detach(struct device *, int flags);
> +void uhidpp_intr(struct uhidev *addr, void *ibuf, u_int len);
> +void uhidpp_refresh(void *);
> +void uhidpp_task(void *);
> +int uhidpp_sleep(struct uhidpp_softc *, uint64_t);
> +
> +void uhidpp_device_connect(struct uhidpp_softc *, struct
> uhidpp_device *);
> +void uhidpp_device_refresh(struct uhidpp_softc *, struct
> uhidpp_device *);
> +
> +struct uhidpp_notification *uhidpp_claim_notification(struct
> uhidpp_softc *);
> +int uhidpp_consume_notification(struct uhidpp_softc *, struct
> uhidpp_report *);
> +int uhidpp_is_notification(struct uhidpp_softc *, struct
> uhidpp_report *);
> +
> +int hidpp_get_protocol_version(struct uhidpp_softc  *, uint8_t, int
> *, int *);
> +
> +int hidpp10_get_name(struct uhidpp_softc *, uint8_t, char *,
> size_t);
> +int hidpp10_get_serial(struct uhidpp_softc *, uint8_t, uint8_t *,
> size_t);
> +int hidpp10_get_type(struct uhidpp_softc *, uint8_t, const char **);
> +int hidpp10_enable_notifications(struct uhidpp_softc *, uint8_t);
> +
> +int hidpp20_root_get_feature(struct uhidpp_softc *, uint8_t,
> uint16_t,
> +    uint8_t *, uint8_t *);
> +int hidpp20_battery_get_level_status(struct uhidpp_softc *, uint8_t,
> uint8_t,
> +    uint8_t *, uint8_t *, uint8_t *);
> +int hidpp20_battery_get_capability(struct uhidpp_softc *, uint8_t,
> uint8_t,
> +    uint8_t *);
> +
> +int hidpp_send_validate(uint8_t, int);
> +int hidpp_send_rap_report(struct uhidpp_softc *, uint8_t, uint8_t,
> +    uint8_t, uint8_t, uint8_t *, int, struct uhidpp_report *);
> +int hidpp_send_fap_report(struct uhidpp_softc *, uint8_t, uint8_t,
> uint8_t,
> +    uint8_t, uint8_t *, int, struct uhidpp_report *);
> +int hidpp_send_report(struct uhidpp_softc *, uint8_t, struct
> uhidpp_report *,
> +    struct uhidpp_report *);
> +
> +struct cfdriver uhidpp_cd = {
> +       NULL, "uhidpp", DV_DULL
> +};
> +
> +const struct cfattach uhidpp_ca = {
> +       sizeof(struct uhidpp_softc),
> +       uhidpp_match,
> +       uhidpp_attach,
> +       uhidpp_detach,
> +};
> +
> +static const struct usb_devno uhidpp_devs[] = {
> +       { USB_VENDOR_LOGITECH,  USB_PRODUCT_ANY },
> +};
> +
> +int
> +uhidpp_match(struct device *parent, void *match, void *aux)
> +{
> +       struct uhidev_attach_arg *uha = (struct uhidev_attach_arg
> *)aux;
> +       void *desc;
> +       int descsiz, siz;
> +
> +       if (uha->reportid != UHIDEV_CLAIM_ALLREPORTID)
> +               return UMATCH_NONE;
> +
> +       if (usb_lookup(uhidpp_devs,
> +                   uha->uaa->vendor, uha->uaa->product) == NULL)
> +               return UMATCH_NONE;
> +
> +       uhidev_get_report_desc(uha->parent, &desc, &descsiz);
> +       siz = hid_report_size(desc, descsiz, hid_output,
> HIDPP_REPORT_ID_SHORT);
> +       if (siz != HIDPP_REPORT_SHORT_LENGTH)
> +               return UMATCH_NONE;
> +       siz = hid_report_size(desc, descsiz, hid_output,
> HIDPP_REPORT_ID_LONG);
> +       if (siz != HIDPP_REPORT_LONG_LENGTH)
> +               return UMATCH_NONE;
> +
> +       return UMATCH_VENDOR_PRODUCT;
> +}
> +
> +void
> +uhidpp_attach(struct device *parent, struct device *self, void *aux)
> +{
> +       struct uhidpp_softc *sc = (struct uhidpp_softc *)self;
> +       struct uhidev_attach_arg *uha = (struct uhidev_attach_arg
> *)aux;
> +       struct usb_attach_arg *uaa = uha->uaa;
> +       int error, i;
> +       int npaired = 0;
> +
> +       sc->sc_hdev.sc_intr = uhidpp_intr;
> +       sc->sc_hdev.sc_udev = uaa->device;
> +       sc->sc_hdev.sc_parent = uha->parent;
> +       sc->sc_hdev.sc_report_id = uha->reportid;
> +       /* The largest supported report dictates the sizes. */
> +       sc->sc_hdev.sc_isize = HIDPP_REPORT_LONG_LENGTH;
> +       sc->sc_hdev.sc_osize = HIDPP_REPORT_LONG_LENGTH;
> +
> +       sc->sc_udev = uaa->device;
> +
> +       mtx_init(&sc->sc_mtx, IPL_USB);
> +
> +       sc->sc_resp = NULL;
> +       sc->sc_resp_state = UHIDPP_RESP_NONE;
> +
> +       error = uhidev_open(&sc->sc_hdev);
> +       if (error) {
> +               printf(" error %d\n", error);
> +               return;
> +       }
> +
> +       usb_init_task(&sc->sc_task, uhidpp_task, sc,
> USB_TASK_TYPE_GENERIC);
> +
> +       mtx_enter(&sc->sc_mtx);
> +
> +       /*
> +        * Wire up report device handlers before issuing commands to
> the device
> +        * in order to receive responses. Necessary as uhidev by
> default
> +        * performs the wiring after the attach routine has returned.
> +        */
> +       uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
> +           HIDPP_REPORT_ID_SHORT);
> +       uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
> +           HIDPP_REPORT_ID_LONG);
> +
> +       /* Probe paired devices. */
> +       for (i = 0; i < UHIDPP_NDEVICES; i++) {
> +               char name[16];
> +               uint8_t serial[4];
> +               struct uhidpp_device *dev = &sc->sc_devices[i];
> +               const char *type;
> +               uint8_t device_id = device_id + 1;
> +
> +               dev->d_id = device_id;
> +
> +               if (hidpp10_get_serial(sc, device_id, serial,
> sizeof(serial)) ||
> +                   hidpp10_get_type(sc, device_id, &type) ||
> +                   hidpp10_get_name(sc, device_id, name,
> sizeof(name)))
> +                       continue;
> +
> +               if (npaired > 0)
> +                       printf(",");
> +               printf(" device %d", device_id);
> +               printf(" %s", type);
> +               printf(" \"%s\"", name);
> +               printf(" serial %02x-%02x-%02x-%02x",
> +                   serial[0], serial[1], serial[2], serial[3]);
> +               npaired++;
> +       }
> +
> +       /* Enable notifications for the receiver. */
> +       error = hidpp10_enable_notifications(sc,
> HIDPP_DEVICE_ID_RECEIVER);
> +       if (error)
> +               printf(" error %d", error);
> +
> +       printf("\n");
> +
> +       strlcpy(sc->sc_sensdev.xname, sc->sc_hdev.sc_dev.dv_xname,
> +           sizeof(sc->sc_sensdev.xname));
> +       sensordev_install(&sc->sc_sensdev);
> +       sc->sc_senstsk = sensor_task_register(sc, uhidpp_refresh, 6);
> +
> +       mtx_leave(&sc->sc_mtx);
> +}
> +
> +int
> +uhidpp_detach(struct device *self, int flags)
> +{
> +       struct uhidpp_softc *sc = (struct uhidpp_softc *)self;
> +       int i, j;
> +
> +       usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
> +
> +       if (sc->sc_senstsk != NULL)
> +               sensor_task_unregister(sc->sc_senstsk);
> +
> +       KASSERT(sc->sc_resp_state == UHIDPP_RESP_NONE);
> +
> +       sensordev_deinstall(&sc->sc_sensdev);
> +
> +       for (i = 0; i < UHIDPP_NDEVICES; i++) {
> +               struct uhidpp_device *dev = &sc->sc_devices[i];
> +
> +               if (!dev->d_connected)
> +                       continue;
> +
> +               for (j = 0; j < UHIDPP_NSENSORS; j++)
> +                       sensor_detach(&sc->sc_sensdev, &dev-
> >d_battery.b_sens[j]);
> +       }
> +
> +       uhidev_close(&sc->sc_hdev);
> +
> +       return 0;
> +}
> +
> +void
> +uhidpp_intr(struct uhidev *addr, void *buf, u_int len)
> +{
> +       struct uhidpp_softc *sc = (struct uhidpp_softc *)addr;
> +       struct uhidpp_report *rep = buf;
> +       int dowake = 0;
> +       uint8_t repid;
> +
> +       /*
> +        * Ugliness ahead as the report ID is stripped of by
> uhidev_intr() but
> +        * needed to determine if an error occurred.
> +        * Note that an error response is always a short report even
> if the
> +        * command that caused the error is a long report.
> +        */
> +       repid = ((uint8_t *)buf)[-1];
> +
> +       DREPORT(__func__, repid, buf, len);
> +
> +       mtx_enter(&sc->sc_mtx);
> +       if (uhidpp_is_notification(sc, rep)) {
> +               struct uhidpp_notification *ntf;
> +
> +               ntf = uhidpp_claim_notification(sc);
> +               if (ntf != NULL) {
> +                       memcpy(&ntf->n_rep, buf, len);
> +                       usb_add_task(sc->sc_udev, &sc->sc_task);
> +               } else {
> +                       DPRINTF("%s: too many notifications",
> __func__);
> +               }
> +       } else {
> +               KASSERT(sc->sc_resp_state == UHIDPP_RESP_WAIT);
> +               dowake = 1;
> +               sc->sc_resp_state = repid;
> +               memcpy(sc->sc_resp, buf, len);
> +       }
> +       mtx_leave(&sc->sc_mtx);
> +       if (dowake)
> +               wakeup(sc);
> +}
> +
> +void
> +uhidpp_refresh(void *arg)
> +{
> +       struct uhidpp_softc *sc = arg;
> +       int i;
> +
> +       mtx_enter(&sc->sc_mtx);
> +       for (i = 0; i < UHIDPP_NDEVICES; i++) {
> +               struct uhidpp_device *dev = &sc->sc_devices[i];
> +
> +               if (dev->d_connected)
> +                       uhidpp_device_refresh(sc, dev);
> +       }
> +       mtx_leave(&sc->sc_mtx);
> +}
> +
> +void
> +uhidpp_task(void *arg)
> +{
> +       struct uhidpp_softc *sc = arg;
> +
> +       mtx_enter(&sc->sc_mtx);
> +       for (;;) {
> +               struct uhidpp_report rep;
> +               struct uhidpp_device *dev;
> +
> +               if (uhidpp_consume_notification(sc, &rep))
> +                       break;
> +
> +               DPRINTF("%s: device_id=%d, sub_id=%02x\n",
> +                   __func__, rep.device_id, rep.rap.sub_id);
> +
> +               if (rep.device_id == 0 || rep.device_id >
> UHIDPP_NDEVICES) {
> +                       DPRINTF("%s: invalid device\n", __func__);
> +                       continue;
> +               }
> +               dev = &sc->sc_devices[rep.device_id - 1];
> +
> +               switch (rep.rap.sub_id) {
> +               case 0x0e:      /* leds */
> +               case 0x40:      /* disconnect */
> +               case 0x4b:      /* pairing accepted */
> +                       break;
> +               case 0x41:      /* connect */
> +                       /*
> +                        * Do nothing if the link is reported to be
> out of
> +                        * range. This happens when a device has been
> idle for a
> +                        * while.
> +                        */
> +                       if (HIDPP_LINK_STATUS(rep.rap.params[0]))
> +                               uhidpp_device_connect(sc, dev);
> +                       break;
> +               }
> +       }
> +       mtx_leave(&sc->sc_mtx);
> +}
> +
> +int
> +uhidpp_sleep(struct uhidpp_softc *sc, uint64_t nsecs)
> +{
> +       return msleep_nsec(sc, &sc->sc_mtx, PZERO, "uhidpp", nsecs);
> +}
> +
> +void
> +uhidpp_device_connect(struct uhidpp_softc *sc, struct uhidpp_device
> *dev)
> +{
> +       struct ksensor *sens;
> +       int error, major, minor;
> +       uint8_t feature_type;
> +
> +       MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
> +
> +       /* A connected device will continously send connect events.
> */
> +       if (dev->d_connected)
> +               return;
> +
> +       error = hidpp_get_protocol_version(sc, dev->d_id, &major,
> &minor);
> +       if (error) {
> +               DPRINTF("%s: protocol version failure: device_id=%d,
> error=%d\n",
> +                   __func__, dev->d_id, error);
> +               return;
> +       }
> +
> +       DPRINTF("%s: device_id=%d, version=%d.%d\n",
> +           __func__, dev->d_id, major, minor);
> +
> +       error = hidpp20_root_get_feature(sc, dev->d_id,
> +           HIDPP20_FEAT_BATTERY_IDX,
> +           &dev->d_battery.b_feature_idx, &feature_type);
> +       if (error) {
> +               DPRINTF("%s: battery feature index failure:
> device_id=%d, "
> +                   "error=%d\n", __func__, dev->d_id, error);
> +               return;
> +       }
> +
> +       error = hidpp20_battery_get_capability(sc, dev->d_id,
> +           dev->d_battery.b_feature_idx, &dev->d_battery.b_nlevels);
> +       if (error) {
> +               DPRINTF("%s: battery capability failure:
> device_id=%d, "
> +                   "error=%d\n", __func__, dev->d_id, error);
> +               return;
> +       }
> +
> +       sens = &dev->d_battery.b_sens[0];
> +       strlcpy(sens->desc, "battery level", sizeof(sens->desc));
> +       sens->type = SENSOR_PERCENT;
> +       sens->flags = SENSOR_FUNKNOWN;
> +       sensor_attach(&sc->sc_sensdev, sens);
> +
> +       sens = &dev->d_battery.b_sens[1];
> +       strlcpy(sens->desc, "battery levels", sizeof(sens->desc));
> +       sens->type = SENSOR_INTEGER;
> +       sens->value = dev->d_battery.b_nlevels;
> +       sensor_attach(&sc->sc_sensdev, sens);
> +
> +       dev->d_connected = 1;
> +       uhidpp_device_refresh(sc, dev);
> +}
> +
> +void
> +uhidpp_device_refresh(struct uhidpp_softc *sc, struct uhidpp_device
> *dev)
> +{
> +       int error;
> +
> +       MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
> +
> +       error = hidpp20_battery_get_level_status(sc, dev->d_id,
> +           dev->d_battery.b_feature_idx,
> +           &dev->d_battery.b_level, &dev->d_battery.b_next_level,
> +           &dev->d_battery.b_status);
> +       if (error) {
> +               DPRINTF("%s: battery level status failure:
> device_id=%d, "
> +                   "error=%d\n", __func__, dev->d_id, error);
> +               return;
> +       }
> +
> +       dev->d_battery.b_sens[0].value = dev->d_battery.b_level *
> 1000;
> +       dev->d_battery.b_sens[0].flags &= ~SENSOR_FUNKNOWN;
> +       if (dev->d_battery.b_nlevels < 10) {
> +               /*
> +                * According to the HID++ 2.0 specification, less
> than 10 levels
> +                * should be mapped to the following 4 levels:
> +                *
> +                * [0, 10]   critical
> +                * [11, 30]  low
> +                * [31, 80]  good
> +                * [81, 100] full
> +                *
> +                * Since sensors are limited to 3 valid statuses,
> clamp it even
> +                * further.
> +                */
> +               if (dev->d_battery.b_level <= 10)
> +                       dev->d_battery.b_sens[0].status =
> SENSOR_S_CRIT;
> +               else if (dev->d_battery.b_level <= 30)
> +                       dev->d_battery.b_sens[0].status =
> SENSOR_S_WARN;
> +               else
> +                       dev->d_battery.b_sens[0].status =
> SENSOR_S_OK;
> +       } else {
> +               /*
> +                * XXX the device supports battery mileage. The
> current level
> +                * must be checked against resp.fap.params[3] given
> by
> +                * hidpp20_battery_get_capability().
> +                */
> +               dev->d_battery.b_sens[0].status = SENSOR_S_UNKNOWN;
> +       }
> +}
> +
> +/*
> + * Returns the next available notification slot, if available.
> + */
> +struct uhidpp_notification *
> +uhidpp_claim_notification(struct uhidpp_softc *sc)
> +{
> +       struct uhidpp_notification *ntf = NULL;
> +       int nclaimed = 0;
> +       int i;
> +
> +       MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
> +
> +       for (i = 0; i < UHIDPP_NNOTIFICATIONS; i++) {
> +               struct uhidpp_notification *tmp = &sc-
> >sc_notifications[i];
> +
> +               if (tmp->n_id > 0)
> +                       nclaimed++;
> +               else if (ntf == NULL)
> +                       ntf = tmp;
> +       }
> +
> +       if (ntf == NULL)
> +               return NULL;
> +       ntf->n_id = nclaimed + 1;
> +       return ntf;
> +}
> +
> +/*
> + * Consume the first unhandled notification, if present.
> + */
> +int
> +uhidpp_consume_notification(struct uhidpp_softc *sc, struct
> uhidpp_report *rep)
> +{
> +       struct uhidpp_notification *ntf = NULL;
> +       int i;
> +
> +       MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
> +
> +       for (i = 0; i < UHIDPP_NNOTIFICATIONS; i++) {
> +               struct uhidpp_notification *tmp = &sc-
> >sc_notifications[i];
> +
> +               if (tmp->n_id > 0 && (ntf == NULL || tmp->n_id < ntf-
> >n_id))
> +                       ntf = tmp;
> +       }
> +       if (ntf == NULL)
> +               return 1;
> +
> +       memcpy(rep, &ntf->n_rep, sizeof(*rep));
> +       ntf->n_id = 0;
> +       return 0;
> +}
> +
> +
> +/*
> + * Returns non-zero if the given report is a notification.
> Otherwise, it must be
> + * a response.
> + */
> +int
> +uhidpp_is_notification(struct uhidpp_softc *sc, struct uhidpp_report
> *rep)
> +{
> +       /* Not waiting for a response. */
> +       if (sc->sc_req == NULL)
> +               return 1;
> +
> +       /* Everything except the parameters must be repeated in a
> response. */
> +       if (sc->sc_req->device_id == rep->device_id &&
> +           sc->sc_req->rap.sub_id == rep->rap.sub_id &&
> +           sc->sc_req->rap.reg_address == rep->rap.reg_address)
> +               return 0;
> +
> +       /* An error must always be a response. */
> +       if ((rep->rap.sub_id == HIDPP_ERROR ||
> +                   rep->fap.feature_index == HIDPP20_ERROR) &&
> +           rep->fap.funcindex_clientid == sc->sc_req-
> >fap.feature_index &&
> +           rep->fap.params[0] == sc->sc_req->fap.funcindex_clientid)
> +               return 0;
> +
> +       return 1;
> +}
> +
> +int
> +hidpp_get_protocol_version(struct uhidpp_softc  *sc, uint8_t
> device_id,
> +    int *major, int *minor)
> +{
> +       struct uhidpp_report resp;
> +       uint8_t params[3] = { 0, 0, HIDPP_FEAT_ROOT_PING_DATA };
> +       int error;
> +
> +       error = hidpp_send_fap_report(sc,
> +           HIDPP_REPORT_ID_SHORT,
> +           device_id,
> +           HIDPP_FEAT_ROOT_IDX,
> +           HIDPP_FEAT_ROOT_PING_FUNC,
> +           params, sizeof(params), &resp);
> +       if (error == HIDPP_ERROR_INVALID_SUBID) {
> +               *major = 1;
> +               *minor = 0;
> +               return 0;
> +       }
> +       if (error)
> +               return error;
> +       if (resp.rap.params[2] != HIDPP_FEAT_ROOT_PING_DATA)
> +               return -EPROTO;
> +
> +       *major = resp.fap.params[0];
> +       *minor = resp.fap.params[1];
> +       return 0;
> +}
> +
> +int
> +hidpp10_get_name(struct uhidpp_softc *sc, uint8_t device_id,
> +    char *buf, size_t bufsiz)
> +{
> +       struct uhidpp_report resp;
> +       int error;
> +       uint8_t params[1] = { 0x40 + (device_id - 1) };
> +       uint8_t len;
> +
> +       error = hidpp_send_rap_report(sc,
> +           HIDPP_REPORT_ID_SHORT,
> +           HIDPP_DEVICE_ID_RECEIVER,
> +           HIDPP_GET_LONG_REGISTER,
> +           HIDPP_REG_PAIRING_INFORMATION,
> +           params, sizeof(params), &resp);
> +       if (error)
> +               return error;
> +
> +       len = resp.rap.params[1];
> +       if (len + 2 > sizeof(resp.rap.params))
> +               return -ENAMETOOLONG;
> +       if (len > bufsiz - 1)
> +               len = bufsiz - 1;
> +       memcpy(buf, &resp.rap.params[2], len);
> +       buf[len] = '\0';
> +       return 0;
> +}
> +
> +int
> +hidpp10_get_serial(struct uhidpp_softc *sc, uint8_t device_id,
> +    uint8_t *buf, size_t bufsiz)
> +{
> +       struct uhidpp_report resp;
> +       int error;
> +       uint8_t params[1] = { 0x30 + (device_id - 1) };
> +       uint8_t len;
> +
> +       error = hidpp_send_rap_report(sc,
> +           HIDPP_REPORT_ID_SHORT,
> +           HIDPP_DEVICE_ID_RECEIVER,
> +           HIDPP_GET_LONG_REGISTER,
> +           HIDPP_REG_PAIRING_INFORMATION,
> +           params, sizeof(params), &resp);
> +       if (error)
> +               return error;
> +
> +       len = 4;
> +       if (bufsiz < len)
> +               len = bufsiz;
> +       memcpy(buf, &resp.rap.params[1], len);
> +       return 0;
> +}
> +
> +int
> +hidpp10_get_type(struct uhidpp_softc *sc, uint8_t device_id, const
> char **type)
> +{
> +       struct uhidpp_report resp;
> +       int error;
> +       uint8_t params[1] = { 0x20 + (device_id - 1) };
> +
> +       error = hidpp_send_rap_report(sc,
> +           HIDPP_REPORT_ID_SHORT,
> +           HIDPP_DEVICE_ID_RECEIVER,
> +           HIDPP_GET_LONG_REGISTER,
> +           HIDPP_REG_PAIRING_INFORMATION,
> +           params, sizeof(params), &resp);
> +       if (error)
> +               return error;
> +
> +       switch (resp.rap.params[7]) {
> +       case 0x00:
> +               *type = "unknown";
> +               return 0;
> +       case 0x01:
> +               *type = "keyboard";
> +               return 0;
> +       case 0x02:
> +               *type = "mouse";
> +               return 0;
> +       case 0x03:
> +               *type = "numpad";
> +               return 0;
> +       case 0x04:
> +               *type = "presenter";
> +               return 0;
> +       case 0x08:
> +               *type = "trackball";
> +               return 0;
> +       case 0x09:
> +               *type = "touchpad";
> +               return 0;
> +       }
> +       return -ENOENT;
> +}
> +
> +int
> +hidpp10_enable_notifications(struct uhidpp_softc *sc, uint8_t
> device_id)
> +{
> +       struct uhidpp_report resp;
> +       uint8_t params[3];
> +
> +       /* Device reporting flags. */
> +       params[0] = HIDPP_NOTIF_DEVICE_BATTERY_STATUS;
> +       /* Receiver reporting flags. */
> +       params[1] = HIDPP_NOTIF_RECEIVER_WIRELESS |
> +           HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT;
> +       /* Device reporting flags (continued). */
> +       params[2] = 0;
> +
> +       return hidpp_send_rap_report(sc,
> +           HIDPP_REPORT_ID_SHORT,
> +           device_id,
> +           HIDPP_SET_REGISTER,
> +           HIDPP_REG_ENABLE_REPORTS,
> +           params, sizeof(params), &resp);
> +}
> +
> +int
> +hidpp20_root_get_feature(struct uhidpp_softc *sc, uint8_t device_id,
> +    uint16_t feature, uint8_t *feature_index, uint8_t *feature_type)
> +{
> +       struct uhidpp_report resp;
> +       uint8_t params[2] = { feature >> 8, feature & 0xff };
> +       int error;
> +
> +       error = hidpp_send_fap_report(sc,
> +           HIDPP_REPORT_ID_LONG,
> +           device_id,
> +           HIDPP20_FEAT_ROOT_IDX,
> +           HIDPP20_FEAT_ROOT_GET_FEATURE_FUNC,
> +           params, sizeof(params), &resp);
> +       if (error)
> +               return error;
> +
> +       if (resp.fap.params[0] == 0)
> +               return -ENOENT;
> +
> +       *feature_index = resp.fap.params[0];
> +       *feature_type = resp.fap.params[1];
> +       return 0;
> +}
> +
> +int
> +hidpp20_battery_get_level_status(struct uhidpp_softc *sc, uint8_t
> device_id,
> +    uint8_t feature_index, uint8_t *level, uint8_t *next_level,
> uint8_t *status)
> +{
> +       struct uhidpp_report resp;
> +       int error;
> +
> +       error = hidpp_send_fap_report(sc,
> +           HIDPP_REPORT_ID_LONG,
> +           device_id,
> +           feature_index,
> +           HIDPP20_FEAT_BATTERY_LEVEL_FUNC,
> +           NULL, 0, &resp);
> +       if (error)
> +               return error;
> +
> +       *level = resp.fap.params[0];
> +       *next_level = resp.fap.params[1];
> +       *status = resp.fap.params[2];
> +       return 0;
> +}
> +
> +int
> +hidpp20_battery_get_capability(struct uhidpp_softc *sc, uint8_t
> device_id,
> +    uint8_t feature_index, uint8_t *nlevels)
> +{
> +       struct uhidpp_report resp;
> +       int error;
> +
> +       error = hidpp_send_fap_report(sc,
> +           HIDPP_REPORT_ID_LONG,
> +           device_id,
> +           feature_index,
> +           HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC,
> +           NULL, 0, &resp);
> +       if (error)
> +               return error;
> +       *nlevels = resp.fap.params[0];
> +       return 0;
> +}
> +
> +int
> +hidpp_send_validate(uint8_t report_id, int nparams)
> +{
> +       if (report_id == HIDPP_REPORT_ID_SHORT) {
> +               if (nparams > HIDPP_REPORT_SHORT_PARAMS_MAX)
> +                       return -EMSGSIZE;
> +       } else if (report_id == HIDPP_REPORT_ID_LONG) {
> +               if (nparams > HIDPP_REPORT_LONG_PARAMS_MAX)
> +                       return -EMSGSIZE;
> +       } else {
> +               return -EINVAL;
> +       }
> +       return 0;
> +}
> +
> +int
> +hidpp_send_fap_report(struct uhidpp_softc *sc, uint8_t report_id,
> +    uint8_t device_id, uint8_t feature_index, uint8_t
> funcindex_clientid,
> +    uint8_t *params, int nparams, struct uhidpp_report *resp)
> +{
> +       struct uhidpp_report req;
> +       int error;
> +
> +       error = hidpp_send_validate(report_id, nparams);
> +       if (error)
> +               return error;
> +
> +       memset(&req, 0, sizeof(req));
> +       req.device_id = device_id;
> +       req.fap.feature_index = feature_index;
> +       req.fap.funcindex_clientid =
> +           (funcindex_clientid << HIDPP_SOFTWARE_ID_LEN) |
> HIDPP_SOFTWARE_ID;
> +       memcpy(req.fap.params, params, nparams);
> +       return hidpp_send_report(sc, report_id, &req, resp);
> +}
> +
> +int
> +hidpp_send_rap_report(struct uhidpp_softc *sc, uint8_t report_id,
> +    uint8_t device_id, uint8_t sub_id, uint8_t reg_address,
> +    uint8_t *params, int nparams, struct uhidpp_report *resp)
> +{
> +       struct uhidpp_report req;
> +       int error;
> +
> +       error = hidpp_send_validate(report_id, nparams);
> +       if (error)
> +               return error;
> +
> +       memset(&req, 0, sizeof(req));
> +       req.device_id = device_id;
> +       req.rap.sub_id = sub_id;
> +       req.rap.reg_address = reg_address;
> +       memcpy(req.rap.params, params, nparams);
> +       return hidpp_send_report(sc, report_id, &req, resp);
> +}
> +
> +int
> +hidpp_send_report(struct uhidpp_softc *sc, uint8_t report_id,
> +    struct uhidpp_report *req, struct uhidpp_report *resp)
> +{
> +       int error, len, n;
> +
> +       MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
> +
> +       if (report_id == HIDPP_REPORT_ID_SHORT)
> +               len = HIDPP_REPORT_SHORT_LENGTH;
> +       else if (report_id == HIDPP_REPORT_ID_LONG)
> +               len = HIDPP_REPORT_LONG_LENGTH;
> +       else
> +               return -EINVAL;
> +
> +       DREPORT(__func__, report_id, data, len);
> +
> +       /* Wait until any ongoing command has completed. */
> +       while (sc->sc_resp_state != UHIDPP_RESP_NONE)
> +               uhidpp_sleep(sc, INFSLP);
> +       sc->sc_req = req;
> +       sc->sc_resp = resp;
> +       sc->sc_resp_state = UHIDPP_RESP_WAIT;
> +       /*
> +        * The mutex must be temporarily released while calling
> +        * uhidev_set_report() as it might end up sleeping.
> +        */
> +       mtx_leave(&sc->sc_mtx);
> +
> +       n = uhidev_set_report(sc->sc_hdev.sc_parent,
> UHID_OUTPUT_REPORT,
> +           report_id, req, len);
> +
> +       mtx_enter(&sc->sc_mtx);
> +       if (len != n) {
> +               error = -EBUSY;
> +               goto out;
> +       }
> +       /*
> +        * The interrupt could already have been received while the
> mutex was
> +        * released. Otherwise, wait for it.
> +        */
> +       if (sc->sc_resp_state == UHIDPP_RESP_WAIT) {
> +               /* Timeout taken from the hid-logitech-hidpp Linux
> driver. */
> +               error = uhidpp_sleep(sc, SEC_TO_NSEC(5));
> +               if (error) {
> +                       error = -error;
> +                       goto out;
> +               }
> +       }
> +
> +       if (sc->sc_resp_state == UHIDPP_RESP_ERROR)
> +               error = -EIO;
> +       else if (sc->sc_resp_state == HIDPP_REPORT_ID_SHORT &&
> +           resp->rap.sub_id == HIDPP_ERROR)
> +               error = resp->rap.params[1];
> +       else if (sc->sc_resp_state == HIDPP_REPORT_ID_LONG &&
> +           resp->fap.feature_index == HIDPP20_ERROR)
> +               error = resp->fap.params[1];
> +
> +out:
> +       sc->sc_req = NULL;
> +       sc->sc_resp = NULL;
> +       sc->sc_resp_state = UHIDPP_RESP_NONE;
> +       wakeup(sc);
> +       return error;
> +}
> +
> +#ifdef UHIDPP_DEBUG
> +
> +void
> +uhidd_dump_report(const char *prefix, uint8_t repid, const unsigned
> char *buf,
> +    u_int buflen)
> +{
> +       u_int i;
> +
> +       printf("%s: %02x ", prefix, repid);
> +       for (i = 0; i < buflen; i++) {
> +               printf("%02x%s", buf[i],
> +                   i == 2 ? " [" : (i + 1 < buflen ? " " : ""));
> +       }
> +       printf("]\n");
> +}
> +
> +#endif
> 
Hi Anton,

this is how dmesg looks after the latest patch (date Tue Feb 02
18:55:17 2021):
uhidev0 at uhub0 port 1 configuration 1 interface 0 "Logitech USB Receiver" rev 
2.00/12.10 addr 3
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes
wskbd1 at ukbd0 mux 1
wskbd1: connecting to wsdisplay0
uhidev1 at uhub0 port 1 configuration 1 interface 1 "Logitech USB Receiver" rev 
2.00/12.10 addr 3
uhidev1: iclass 3/1, 8 report ids
ums0 at uhidev1 reportid 2: 16 buttons, Z and W dir
wsmouse2 at ums0 mux 0
uhid0 at uhidev1 reportid 3: input=4, output=0, feature=0
uhid1 at uhidev1 reportid 4: input=1, output=0, feature=0
uhid2 at uhidev1 reportid 8: input=1, output=0, feature=0
uhidev2 at uhub0 port 1 configuration 1 interface 2 "Logitech USB Receiver" rev 
2.00/12.10 addr 3
uhidev2: iclass 3/0, 33 report ids
uhidpp0 at uhidev2uhidpp_intr: 11 ff 83 b5 [30 c4 b4 96 9e 04 00 00 00 01 00 00 
00 00 00 00]
uhidpp_intr: 11 ff 83 b5 [20 09 08 10 1b 04 00 02 06 00 00 00 00 00 00 00]
uhidpp_intr: 11 ff 83 b5 [40 04 4d 37 30 35 00 00 00 00 00 00 00 00 00 00]
 device 1 mouse "M705" serial c4-b4-96-9euhidpp_intr: 11 ff 83 b5 [31 8d 37 6a 
6f 1a 40 00 00 03 00 00 00 00 00 00]
 uhidpp_intr: 11 ff 83 b5 [21 08 14 40 02 04 00 01 07 00 00 00 00 00 00 00]
 uhidpp_intr: 11 ff 83 b5 [41 04 4b 37 35 30 00 00 00 00 00 00 00 00 00 00]
 , device 2 keyboard "K750" serial 8d-37-6a-6fuhidpp_intr: 10 ff 8f 83 [b5 03 
00]
 uhidpp_intr: 10 ff 8f 83 [b5 03 00]
 uhidpp_intr: 10 ff 8f 83 [b5 03 00]
 uhidpp_intr: 10 ff 8f 83 [b5 03 00]
 uhidpp_intr: 10 ff 80 00 [00 00 00]

 uhidpp_intr: 10 01 41 04 [92 1b 10]
 uhidpp_task: device_id=1, sub_id=41
 uhidpp_intr: 10 01 4b 01 [00 00 00]
 uhidpp_intr: 10 01 8f 00 [11 01 00]
 uhidpp_device_connect: device_id=1, version=1.0
 uhidpp_intr: 10 01 8f 00 [01 01 00]
 uhidpp_device_connect: battery feature index failure: device_id=1, error=1
 uhidpp_task: device_id=1, sub_id=4b
 uhidpp_intr: 10 01 41 04 [52 1b 10]
 uhidpp_task: device_id=1, sub_id=4

and indeed, kernel panic is gone. The last event in dmesg is when I
switched the mouse off. There was a missing variable or typo which
caused build to fail. The error was:
src/sys/dev/usb/uhidpp.c:986:31: error: use of undeclared identifier
'data'
        DREPORT(__func__, report_id, data, len);

As a workaround I commented out that line to proceed as it only seemed
to be a
debug print.

Thanks.

--
Kind regards,
Ville






Reply via email to