Re: [Diff] Keyboard backlight support for late powerbooks, plus keybindings

2023-07-23 Thread Anton Lindqvist
On Sun, Jul 23, 2023 at 11:37:38AM +, jon@elytron.openbsd.amsterdam wrote:
> Hello all. Thank you very much for your input. I have taken heed of
> your suggestions in the diff below
> 
> On Sat, 22 Jul 2023 20:59:04 -0400 George Koehler 
> wrote:
> 
> > We should check if (wskbd_get_backlight != NULL), like we do for
> > WSKBDIO_GETBACKLIGHT.  Same for wskbd_set_backlight.
> 
> Fixed. I am returning 0 if they are NULL, is that acceptable?
> Index: arch/macppc/dev/adb.c
> ===
> RCS file: /cvs/src/sys/arch/macppc/dev/adb.c,v
> retrieving revision 1.50
> diff -u -p -r1.50 adb.c
> --- arch/macppc/dev/adb.c 11 Apr 2023 00:45:07 -  1.50
> +++ arch/macppc/dev/adb.c 23 Jul 2023 11:10:27 -
> @@ -96,6 +96,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -242,6 +243,12 @@ void setsoftadb(void);
>  int  adb_intr(void *arg);
>  void adb_cuda_autopoll(void);
>  void adb_cuda_fileserver_mode(void);
> +uint8_t pmu_backlight; /* keyboard backlight value */
> +int  pmu_get_backlight(struct wskbd_backlight *);
> +int  pmu_set_backlight(struct wskbd_backlight *);
> +extern int (*wskbd_get_backlight)(struct wskbd_backlight *);
> +extern int (*wskbd_set_backlight)(struct wskbd_backlight *);
> +
>  
>  #ifndef SMALL_KERNEL
>  void adb_shutdown(void *);
> @@ -1730,8 +1737,11 @@ adbattach(struct device *parent, struct 
>  
>   if (adbHardware == ADB_HW_CUDA)
>   adb_cuda_fileserver_mode();
> - if (adbHardware == ADB_HW_PMU)
> + if (adbHardware == ADB_HW_PMU) {
> + wskbd_get_backlight = pmu_get_backlight;
> + wskbd_set_backlight = pmu_set_backlight;
>   pmu_fileserver_mode(1);
> + }
>  
>   /*
>* XXX If the machine doesn't have an ADB bus (PowerBook5,6+)
> @@ -1757,4 +1767,20 @@ adbattach(struct device *parent, struct 
>   if (adbHardware == ADB_HW_CUDA)
>   adb_cuda_autopoll();
>   adb_polling = 0;
> +}
> +
> +int
> +pmu_get_backlight(struct wskbd_backlight *kbl)
> +{
> + kbl->min = 0;
> + kbl->max = 0xff;
> + kbl->curval = pmu_backlight;
> + return 0;
> +}
> +
> +int
> +pmu_set_backlight(struct wskbd_backlight *kbl)
> +{
> + pmu_backlight = kbl->curval;
> + return pmu_set_kbl(pmu_backlight);
>  }
> Index: arch/macppc/dev/pm_direct.c
> ===
> RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.c,v
> retrieving revision 1.34
> diff -u -p -r1.34 pm_direct.c
> --- arch/macppc/dev/pm_direct.c   28 Dec 2022 07:40:23 -  1.34
> +++ arch/macppc/dev/pm_direct.c   23 Jul 2023 11:10:29 -
> @@ -853,3 +853,22 @@ pmu_fileserver_mode(int on)
>   }
>   pmgrop();
>  }
> +
> +int
> +pmu_set_kbl(unsigned int level)
> +{
> + if (level > 0xff)
> + return (EINVAL);
> +
> + PMData p;
> +
> + p.command = 0x4F;
> + p.num_data = 3;
> + p.s_buf = p.r_buf = p.data;
> + p.data[0] = 0;
> + p.data[1] = 0;
> + p.data[2] = level;
> + pmgrop();
> + return (0);
> +}
> +
> Index: arch/macppc/dev/pm_direct.h
> ===
> RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.h,v
> retrieving revision 1.15
> diff -u -p -r1.15 pm_direct.h
> --- arch/macppc/dev/pm_direct.h   21 Oct 2022 22:42:36 -  1.15
> +++ arch/macppc/dev/pm_direct.h   23 Jul 2023 11:10:29 -
> @@ -67,6 +67,7 @@ struct pmu_battery_info
>  };
>  
>  int pm_battery_info(int, struct pmu_battery_info *);
> +int pmu_set_kbl(unsigned int);
>  
>  void pm_eject_pcmcia(int);
>  void pmu_fileserver_mode(int);
> Index: dev/hid/hidkbd.c
> ===
> RCS file: /cvs/src/sys/dev/hid/hidkbd.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 hidkbd.c
> --- dev/hid/hidkbd.c  9 Jul 2023 08:02:13 -   1.9
> +++ dev/hid/hidkbd.c  23 Jul 2023 11:10:34 -
> @@ -143,6 +143,9 @@ static const struct hidkbd_translation a
>   { 60, 127 },/* F3 -> audio mute */
>   { 61, 129 },/* F4 -> audio lower */
>   { 62, 128 },/* F5 -> audio raise */
> + { 65, 234 },/* F8 -> backlight toggle*/
> + { 66, 236 },/* F9 -> backlight lower */
> + { 67, 235 },/* F10 -> backlight raise*/
>  #else
>   { 63, 102 },/* F6 -> sleep */
>   { 67, 127 },/* F10 -> audio mute */
> @@ -569,6 +572,9 @@ hidkbd_decode(struct hidkbd *kbd, struct
>   case 129:
>   case 232:
>   case 233:
> + case 234:
> + case 235:
> + case 236:
>   wskbd_input(kbd->sc_wskbddev,
>   key & RELEASE ?  WSCONS_EVENT_KEY_UP :
> WSCONS_EVENT_KEY_DOWN, key & CODEMASK);
> Index: 

regress test results

2022-12-19 Thread Anton Lindqvist
Hi,
My daily regress test results are now publicly available in an almost
identical format as the one bluhm@ already is providing[1]. This not a
competing source of any kind but rather complementary as our
environments are slightly different.

https://regress.basename.se/

Some things worth mentioning:

1. For amd64 where I also build snapshots, a precise CVS delta is
   included relative to the previous run.

2. In case of a non pass run, only the x?failed/skipped/disabled targets
   are extracted from the log. Makes it easier to highlight the
   problematic targets.

3. Only failures contribute to the score used during sorting, I still
   haven't decided if this is a good idea or not. The other option is to
   also give weight to skip/xfail targets.

[1] http://bluhm.genua.de/regress/results/latest.html



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

2022-11-25 Thread Anton Lindqvist
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?

diff --git sys/dev/usb/uhidpp.c sys/dev/usb/uhidpp.c
index 83e58d56fc9..5b9ef198948 100644
--- sys/dev/usb/uhidpp.c
+++ sys/dev/usb/uhidpp.c
@@ -29,7 +29,7 @@
 #include 
 #include 
 
-/* #define UHIDPP_DEBUG */
+#define UHIDPP_DEBUG
 #ifdef UHIDPP_DEBUG
 
 #define DPRINTF(x...) do { \
@@ -125,6 +125,15 @@ int uhidpp_debug = 1;
 #define HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC   0x0001
 #define  HIDPP20_CAPABILITY_RECHARGEABLE   0x0004
 
+#define HIDPP20_FEAT_UNIFIED_BATTERY_ID0x1004
+#define HIDPP20_FEAT_UNIFIED_BATTERY_CAPABILITIES_FUNC 0x
+#define  HIDPP20_CAPABILITES_RECHARGEABLE  0x0002
+#define HIDPP20_FEAT_UNIFIED_BATTERY_STATUS_FUNC   0x0001
+#define  HIDPP20_BATTERY_STATUS_CRITICAL   0x0001
+#define  HIDPP20_BATTERY_STATUS_LOW0x0002
+#define  HIDPP20_BATTERY_STATUS_GOOD   0x0004
+#define  HIDPP20_BATTERY_STATUS_FULL   0x0008
+
 /* HID++ 2.0 error codes. */
 #define HIDPP20_ERROR  0xff
 #define HIDPP20_ERROR_NO_ERROR 0x00
@@ -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
 
struct {
struct ksensor sens[UHIDPP_NSENSORS];
uint8_t feature_idx;
uint8_t nlevels;
+   uint8_t unified_level_mask;
uint8_t rechargeable;
} d_battery;
 };
 
 /*
  * Locking:
+ * [I] immutable
  * [m] sc_mtx
  */
 struct uhidpp_softc {
@@ -226,6 +238,11 @@ struct uhidpp_softc {
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 */
+
+   enum {
+   UHIDPP_RECEIVER_UNIFYING,
+   UHIDPP_RECEIVER_BOLT,
+   } sc_receiver;  /* [I] */
 };
 
 int uhidpp_match(struct device *, void *, void *);
@@ -264,6 +281,11 @@ int hidpp20_battery_get_level_status(struct uhidpp_softc *,
 int hidpp20_battery_get_capability(struct uhidpp_softc *,
 struct uhidpp_device *);
 int hidpp20_battery_status_is_charging(uint8_t);
+int hidpp20_unified_battery_get_capabilities(struct uhidpp_softc *,
+struct uhidpp_device *);
+int hidpp20_unified_battery_get_status(struct uhidpp_softc *,
+struct uhidpp_device *);
+int hidpp20_unified_battery_status_is_charging(uint8_t);
 
 int hidpp_send_validate(uint8_t, int);
 int hidpp_send_rap_report(struct uhidpp_softc *, uint8_t, uint8_t, uint8_t,
@@ -273,6 +295,18 @@ int hidpp_send_fap_report(struct uhidpp_softc *, uint8_t, 
uint8_t, uint8_t,
 int hidpp_send_report(struct uhidpp_softc *, uint8_t, struct uhidpp_report *,
 struct uhidpp_report *);
 
+static uint8_t
+nlevels(uint8_t mask)
+{
+   uint8_t nbits = 0;
+
+   for (; mask > 0; mask >>= 1) {
+   if (mask & 1)
+   nbits++;
+   }
+   return nbits;
+}
+
 struct cfdriver uhidpp_cd = {
NULL, "uhidpp", DV_DULL
 };
@@ -369,6 +403,11 @@ uhidpp_attach(struct device *parent, struct device *self, 
void *aux)
return;
}
 
+   if (uaa->product == 0xc548)
+   sc->sc_receiver = UHIDPP_RECEIVER_BOLT;
+   else
+   sc->sc_receiver = UHIDPP_RECEIVER_UNIFYING;
+
/* Probe paired devices. */
for (i = 0; i < UHIDPP_NDEVICES; i++) {
char name[16];
@@ -573,7 +612,10 @@ uhidpp_device_connect(struct uhidpp_softc *sc, struct 
uhidpp_device *dev)
return;
}
 
-   error = hidpp20_battery_get_capability(sc, dev);
+   if (dev->d_features & UHIDPP_DEVICE_FEATURE_BATTERY)
+   error = hidpp20_battery_get_capability(sc, dev);
+   else if (dev->d_features & UHIDPP_DEVICE_FEATURE_UNIFIIED_BATTERY)
+   error = hidpp20_unified_battery_get_capabilities(sc, dev);
if (error) {
DPRINTF("%s: battery capability failure: device_id=%d, "
 

Microsoft Surface: replace umstc(4) with ucc(4)

2022-11-17 Thread Anton Lindqvist
Hi,
umstc is essentially a less capable version of ucc. Now that matthieu@
recently taught wskbd to adjust the brightness in process context, we
should be able to get rid of umstc in favor of ucc.

In order for ucc to be feature compatible with umstc, it must honor the
always open quirk as pointed out by jcs@ earlier.

I don't have access to any umstc hardware. Could someone with such
hardware try the following diff? Ideally, umstc should no longer attach
whereas ucc should. A dmesg before and after would be helpful.

diff --git sys/dev/usb/ucc.c sys/dev/usb/ucc.c
index acc14ce86cf..25b391fd9ee 100644
--- sys/dev/usb/ucc.c
+++ sys/dev/usb/ucc.c
@@ -20,6 +20,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -29,6 +30,7 @@
 struct ucc_softc {
struct uhidevsc_hdev;
struct hidcc*sc_cc;
+   u_int32_tsc_quirks;
 };
 
 intucc_match(struct device *, void *, void *);
@@ -76,6 +78,8 @@ ucc_attach(struct device *parent, struct device *self, void 
*aux)
void *desc;
int repid, size;
 
+   sc->sc_quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
+
sc->sc_hdev.sc_intr = ucc_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_udev = uha->uaa->device;
@@ -98,6 +102,9 @@ ucc_attach(struct device *parent, struct device *self, void 
*aux)
.arg= self,
};
sc->sc_cc = hidcc_attach();
+
+   if (sc->sc_quirks & UQ_ALWAYS_OPEN)
+   uhidev_open(>sc_hdev);
 }
 
 int
@@ -127,6 +134,9 @@ ucc_enable(void *v, int on)
struct ucc_softc *sc = (struct ucc_softc *)v;
int error = 0;
 
+   if (sc->sc_quirks & UQ_ALWAYS_OPEN)
+   return 0;
+
if (on)
error = uhidev_open(>sc_hdev);
else
diff --git sys/dev/usb/umstc.c sys/dev/usb/umstc.c
index 4bebeb41811..c3be6cce41f 100644
--- sys/dev/usb/umstc.c
+++ sys/dev/usb/umstc.c
@@ -80,6 +80,8 @@ umstc_match(struct device *parent, void *match, void *aux)
int size;
void *desc;
 
+   return (UMATCH_NONE);
+
if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (UMATCH_NONE);
 



Re: ampintc: minor nits

2022-08-15 Thread Anton Lindqvist
On Mon, Jul 18, 2022 at 12:37:00PM +0200, Anton Lindqvist wrote:
> On Fri, Jul 15, 2022 at 06:58:33PM +0200, Mark Kettenis wrote:
> > > Date: Mon, 11 Jul 2022 16:21:39 +0200
> > > From: Anton Lindqvist 
> > > 
> > > On Mon, Jul 11, 2022 at 09:02:20AM +0200, Mark Kettenis wrote:
> > > > > Date: Mon, 11 Jul 2022 08:35:44 +0200
> > > > > From: Anton Lindqvist 
> > > > > 
> > > > > Hi,
> > > > > Addressing the following nits made it easier for me to grasp the 
> > > > > ampintc
> > > > > implementation while reading the specification. There's also one 
> > > > > missing
> > > > > NULL check included.
> > > > > 
> > > > > Too verbose or does anyone else consider this an improvement?
> > > > 
> > > > Your timing is a but unfortunate since I just posted the
> > > > suspend/resume diff that will conflict with this.
> > > > 
> > > > Some/all of this may be useful, but not right now :(.
> > > 
> > > That was actually the thing that reminded me about this diff :)
> > > I can wait until things have stabilized and send out a new diff.
> > 
> > Right.  I actually have another change coming, but that one won't
> > conflict.
> 
> Here's the rebased diff.

Ping

> 
> diff --git sys/arch/arm64/dev/ampintc.c sys/arch/arm64/dev/ampintc.c
> index 45a15dd2d57..c569c88cc2b 100644
> --- sys/arch/arm64/dev/ampintc.c
> +++ sys/arch/arm64/dev/ampintc.c
> @@ -125,6 +125,13 @@
>  #define ICPHPIR  0x18
>  #define ICPIIR   0xFC
>  
> +/* Sofware Generated Interrupts (SGI) */
> +#define SGI_MIN  0
> +#define SGI_MAX  15
> +/* Private Peripheral Interrupts (PPI) */
> +#define PPI_MIN  16
> +#define PPI_MAX  31
> +
>  /*
>   * what about periph_id and component_id
>   */
> @@ -237,7 +244,7 @@ ampintc_attach(struct device *parent, struct device 
> *self, void *aux)
>  {
>   struct ampintc_softc *sc = (struct ampintc_softc *)self;
>   struct fdt_attach_args *faa = aux;
> - int i, nintr, ncpu;
> + int i, ncpu, nintr, nlines;
>   uint32_t ictr;
>  #ifdef MULTIPROCESSOR
>   int nipi, ipiirq[3];
> @@ -262,8 +269,9 @@ ampintc_attach(struct device *parent, struct device 
> *self, void *aux)
>   evcount_attach(>sc_spur, "irq1023/spur", NULL);
>  
>   ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
> - nintr = 32 * ((ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M);
> - nintr += 32; /* ICD_ICTR + 1, irq 0-31 is SGI, 32+ is PPI */
> + nlines = (ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M;
> + /* Account for SGI + PPI = 16 + 16 = 32 */
> + nintr = 32 * (nlines + 1);
>   sc->sc_nintr = nintr;
>   ncpu = ((ictr >> ICD_ICTR_CPU_SH) & ICD_ICTR_CPU_M) + 1;
>   printf(" nirq %d, ncpu %d", nintr, ncpu);
> @@ -302,7 +310,7 @@ ampintc_attach(struct device *parent, struct device 
> *self, void *aux)
>* the non-secure OS.
>*/
>   nipi = 0;
> - for (i = 0; i < 16; i++) {
> + for (i = 0; i <= SGI_MAX; i++) {
>   int reg, oldreg;
>  
>   oldreg = bus_space_read_1(sc->sc_iot, sc->sc_d_ioh,
> @@ -417,7 +425,8 @@ ampintc_activate(struct device *self, int act)
>  void
>  ampintc_init(struct ampintc_softc *sc)
>  {
> - int i;
> + uint32_t ictr;
> + int i, nconfigs, nlines;
>  
>   /* Disable all interrupts, clear all pending */
>   for (i = 0; i < sc->sc_nintr / 32; i++) {
> @@ -432,8 +441,20 @@ ampintc_init(struct ampintc_softc *sc)
>   /* target no cpus */
>   bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(i), 0);
>   }
> - for (i = 2; i < sc->sc_nintr / 16; i++) {
> - /* irq 32 - N */
> +
> + /*
> +  * Reset edge/level configuration for all interrupts where each
> +  * interrupt is represented using 2 bits and each configuration register
> +  * being 32 bits wide. Each configuration register therefore covers 16
> +  * configurations.
> +  *
> +  * Since SGI are read only and PPI might not be programmable skip the
> +  * first 2*(16 + 16)/32 = 2 configuration registers.
> +  */
> + ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
> + nlines = (ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M;
> + nconfigs = 2 * (nlines + 1);
> + for (i = 2; i < nconfigs; i++) {
>   bus_space_write_4(sc->sc_iot, sc->sc_d_ioh,
>   ICD_ICRn(i * 16), 0);
>   }
> @@ -828,10 +849,10 @@ ampintc_intr_establish(int irqno, int type, int level, 
> struct cpu_info *ci,
>   if (ci == NULL)
>   ci = _info_primary;
>  
> - if (irqno < 16) {
> + if (irqno <= SGI_MAX) {
>   /* SGI are only EDGE */
>   type = IST_EDGE_RISING;
> - } else if (irqno < 32) {
> + } else if (irqno <= PPI_MAX) {
>   /* PPI are only LEVEL */
>   type = IST_LEVEL_HIGH;
>   }



Re: ampintc: minor nits

2022-07-18 Thread Anton Lindqvist
On Fri, Jul 15, 2022 at 06:58:33PM +0200, Mark Kettenis wrote:
> > Date: Mon, 11 Jul 2022 16:21:39 +0200
> > From: Anton Lindqvist 
> > 
> > On Mon, Jul 11, 2022 at 09:02:20AM +0200, Mark Kettenis wrote:
> > > > Date: Mon, 11 Jul 2022 08:35:44 +0200
> > > > From: Anton Lindqvist 
> > > > 
> > > > Hi,
> > > > Addressing the following nits made it easier for me to grasp the ampintc
> > > > implementation while reading the specification. There's also one missing
> > > > NULL check included.
> > > > 
> > > > Too verbose or does anyone else consider this an improvement?
> > > 
> > > Your timing is a but unfortunate since I just posted the
> > > suspend/resume diff that will conflict with this.
> > > 
> > > Some/all of this may be useful, but not right now :(.
> > 
> > That was actually the thing that reminded me about this diff :)
> > I can wait until things have stabilized and send out a new diff.
> 
> Right.  I actually have another change coming, but that one won't
> conflict.

Here's the rebased diff.

diff --git sys/arch/arm64/dev/ampintc.c sys/arch/arm64/dev/ampintc.c
index 45a15dd2d57..c569c88cc2b 100644
--- sys/arch/arm64/dev/ampintc.c
+++ sys/arch/arm64/dev/ampintc.c
@@ -125,6 +125,13 @@
 #define ICPHPIR0x18
 #define ICPIIR 0xFC
 
+/* Sofware Generated Interrupts (SGI) */
+#define SGI_MIN0
+#define SGI_MAX15
+/* Private Peripheral Interrupts (PPI) */
+#define PPI_MIN16
+#define PPI_MAX31
+
 /*
  * what about periph_id and component_id
  */
@@ -237,7 +244,7 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
 {
struct ampintc_softc *sc = (struct ampintc_softc *)self;
struct fdt_attach_args *faa = aux;
-   int i, nintr, ncpu;
+   int i, ncpu, nintr, nlines;
uint32_t ictr;
 #ifdef MULTIPROCESSOR
int nipi, ipiirq[3];
@@ -262,8 +269,9 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
evcount_attach(>sc_spur, "irq1023/spur", NULL);
 
ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
-   nintr = 32 * ((ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M);
-   nintr += 32; /* ICD_ICTR + 1, irq 0-31 is SGI, 32+ is PPI */
+   nlines = (ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M;
+   /* Account for SGI + PPI = 16 + 16 = 32 */
+   nintr = 32 * (nlines + 1);
sc->sc_nintr = nintr;
ncpu = ((ictr >> ICD_ICTR_CPU_SH) & ICD_ICTR_CPU_M) + 1;
printf(" nirq %d, ncpu %d", nintr, ncpu);
@@ -302,7 +310,7 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
 * the non-secure OS.
 */
nipi = 0;
-   for (i = 0; i < 16; i++) {
+   for (i = 0; i <= SGI_MAX; i++) {
int reg, oldreg;
 
oldreg = bus_space_read_1(sc->sc_iot, sc->sc_d_ioh,
@@ -417,7 +425,8 @@ ampintc_activate(struct device *self, int act)
 void
 ampintc_init(struct ampintc_softc *sc)
 {
-   int i;
+   uint32_t ictr;
+   int i, nconfigs, nlines;
 
/* Disable all interrupts, clear all pending */
for (i = 0; i < sc->sc_nintr / 32; i++) {
@@ -432,8 +441,20 @@ ampintc_init(struct ampintc_softc *sc)
/* target no cpus */
bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(i), 0);
}
-   for (i = 2; i < sc->sc_nintr / 16; i++) {
-   /* irq 32 - N */
+
+   /*
+* Reset edge/level configuration for all interrupts where each
+* interrupt is represented using 2 bits and each configuration register
+* being 32 bits wide. Each configuration register therefore covers 16
+* configurations.
+*
+* Since SGI are read only and PPI might not be programmable skip the
+* first 2*(16 + 16)/32 = 2 configuration registers.
+*/
+   ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
+   nlines = (ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M;
+   nconfigs = 2 * (nlines + 1);
+   for (i = 2; i < nconfigs; i++) {
bus_space_write_4(sc->sc_iot, sc->sc_d_ioh,
ICD_ICRn(i * 16), 0);
}
@@ -828,10 +849,10 @@ ampintc_intr_establish(int irqno, int type, int level, 
struct cpu_info *ci,
if (ci == NULL)
ci = _info_primary;
 
-   if (irqno < 16) {
+   if (irqno <= SGI_MAX) {
/* SGI are only EDGE */
type = IST_EDGE_RISING;
-   } else if (irqno < 32) {
+   } else if (irqno <= PPI_MAX) {
/* PPI are only LEVEL */
type = IST_LEVEL_HIGH;
}



Re: ampintc: minor nits

2022-07-11 Thread Anton Lindqvist
On Mon, Jul 11, 2022 at 09:02:20AM +0200, Mark Kettenis wrote:
> > Date: Mon, 11 Jul 2022 08:35:44 +0200
> > From: Anton Lindqvist 
> > 
> > Hi,
> > Addressing the following nits made it easier for me to grasp the ampintc
> > implementation while reading the specification. There's also one missing
> > NULL check included.
> > 
> > Too verbose or does anyone else consider this an improvement?
> 
> Your timing is a but unfortunate since I just posted the
> suspend/resume diff that will conflict with this.
> 
> Some/all of this may be useful, but not right now :(.

That was actually the thing that reminded me about this diff :)
I can wait until things have stabilized and send out a new diff.



ampintc: minor nits

2022-07-11 Thread Anton Lindqvist
Hi,
Addressing the following nits made it easier for me to grasp the ampintc
implementation while reading the specification. There's also one missing
NULL check included.

Too verbose or does anyone else consider this an improvement?

diff --git sys/arch/arm64/dev/ampintc.c sys/arch/arm64/dev/ampintc.c
index 3983aa5ed08..6407793e9b8 100644
--- sys/arch/arm64/dev/ampintc.c
+++ sys/arch/arm64/dev/ampintc.c
@@ -125,6 +125,13 @@
 #define ICPHPIR0x18
 #define ICPIIR 0xFC
 
+/* Sofware Generated Interrupts (SGI) */
+#define SGI_MIN0
+#define SGI_MAX15
+/* Private Peripheral Interrupts (PPI) */
+#define PPI_MIN16
+#define PPI_MAX31
+
 /*
  * what about periph_id and component_id
  */
@@ -233,7 +240,7 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
 {
struct ampintc_softc *sc = (struct ampintc_softc *)self;
struct fdt_attach_args *faa = aux;
-   int i, nintr, ncpu;
+   int i, ncpu, nconfigs, nintr, nlines;
uint32_t ictr;
 #ifdef MULTIPROCESSOR
int nipi, ipiirq[2];
@@ -258,8 +265,9 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
evcount_attach(>sc_spur, "irq1023/spur", NULL);
 
ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
-   nintr = 32 * ((ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M);
-   nintr += 32; /* ICD_ICTR + 1, irq 0-31 is SGI, 32+ is PPI */
+   nlines = (ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M;
+   /* Account for SGI + PPI = 16 + 16 = 32 */
+   nintr = 32 * (nlines + 1);
sc->sc_nintr = nintr;
ncpu = ((ictr >> ICD_ICTR_CPU_SH) & ICD_ICTR_CPU_M) + 1;
printf(" nirq %d, ncpu %d", nintr, ncpu);
@@ -281,10 +289,19 @@ ampintc_attach(struct device *parent, struct device 
*self, void *aux)
/* target no cpus */
bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(i), 0);
}
-   for (i = 2; i < nintr/16; i++) {
-   /* irq 32 - N */
+
+   /*
+* Reset edge/level configuration for all interrupts where each
+* interrupt is represented using 2 bits and each configuration register
+* being 32 bits wide. Each configuration register therefore covers 16
+* configurations.
+*
+* Since SGI are read only and PPI might not be programmable skip the
+* first 2*(16 + 16)/32 = 2 configuration registers.
+*/
+   nconfigs = 2 * (nlines + 1);
+   for (i = 2; i < nconfigs; i++)
bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICRn(i*16), 0);
-   }
 
/* software reset of the part? */
/* set protection bit (kernel only)? */
@@ -293,6 +310,8 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
 
sc->sc_handler = mallocarray(nintr, sizeof(*sc->sc_handler), M_DEVBUF,
M_ZERO | M_NOWAIT);
+   if (sc->sc_handler == NULL)
+   panic("%s: cannot allocate irq handlers", __func__);
for (i = 0; i < nintr; i++) {
TAILQ_INIT(>sc_handler[i].iq_list);
}
@@ -313,7 +332,7 @@ ampintc_attach(struct device *parent, struct device *self, 
void *aux)
 * possible that most are not available to the non-secure OS.
 */
nipi = 0;
-   for (i = 0; i < 16; i++) {
+   for (i = 0; i <= SGI_MAX; i++) {
int reg, oldreg;
 
oldreg = bus_space_read_1(sc->sc_iot, sc->sc_d_ioh,
@@ -762,10 +781,10 @@ ampintc_intr_establish(int irqno, int type, int level, 
struct cpu_info *ci,
if (ci == NULL)
ci = _info_primary;
 
-   if (irqno < 16) {
+   if (irqno <= SGI_MAX) {
/* SGI are only EDGE */
type = IST_EDGE_RISING;
-   } else if (irqno < 32) {
+   } else if (irqno <= PPI_MAX) {
/* PPI are only LEVEL */
type = IST_LEVEL_HIGH;
}



Re: amd64 serial console changes

2022-06-30 Thread Anton Lindqvist
On Thu, Jun 30, 2022 at 01:07:46PM +0200, Mark Kettenis wrote:
> Ah right.  Please commit!

Here's the complete diff, ok?

diff --git sys/arch/amd64/stand/efi32/exec_i386.c 
sys/arch/amd64/stand/efi32/exec_i386.c
index 8349d97fefb..21f13cd273b 100644
--- sys/arch/amd64/stand/efi32/exec_i386.c
+++ sys/arch/amd64/stand/efi32/exec_i386.c
@@ -66,7 +66,7 @@ run_loadfile(uint64_t *marks, int howto)
dev_t bootdev = bootdev_dip->bootdev;
size_t ac = BOOTARG_LEN;
caddr_t av = (caddr_t)BOOTARG_OFF;
-   bios_consdev_t cd;
+   bios_oconsdev_t cd;
extern int com_speed; /* from bioscons.c */
extern int com_addr;
bios_ddb_t ddb;
diff --git sys/arch/amd64/stand/efi64/exec_i386.c 
sys/arch/amd64/stand/efi64/exec_i386.c
index 48e460cb040..043193f93be 100644
--- sys/arch/amd64/stand/efi64/exec_i386.c
+++ sys/arch/amd64/stand/efi64/exec_i386.c
@@ -66,7 +66,7 @@ run_loadfile(uint64_t *marks, int howto)
dev_t bootdev = bootdev_dip->bootdev;
size_t ac = BOOTARG_LEN;
caddr_t av = (caddr_t)BOOTARG_OFF;
-   bios_consdev_t cd;
+   bios_oconsdev_t cd;
extern int com_speed; /* from bioscons.c */
extern int com_addr;
bios_ddb_t ddb;
diff --git sys/arch/amd64/stand/efiboot/exec_i386.c 
sys/arch/amd64/stand/efiboot/exec_i386.c
index ea8fa67820b..70ff23c9d32 100644
--- sys/arch/amd64/stand/efiboot/exec_i386.c
+++ sys/arch/amd64/stand/efiboot/exec_i386.c
@@ -72,7 +72,7 @@ run_loadfile(uint64_t *marks, int howto)
dev_t bootdev = bootdev_dip->bootdev;
size_t ac = BOOTARG_LEN;
caddr_t av = (caddr_t)BOOTARG_OFF;
-   bios_consdev_t cd;
+   bios_oconsdev_t cd;
extern int com_speed; /* from bioscons.c */
extern int com_addr;
bios_ddb_t ddb;
diff --git sys/arch/amd64/stand/libsa/exec_i386.c 
sys/arch/amd64/stand/libsa/exec_i386.c
index 22067931829..25d20d359c0 100644
--- sys/arch/amd64/stand/libsa/exec_i386.c
+++ sys/arch/amd64/stand/libsa/exec_i386.c
@@ -91,7 +91,7 @@ run_loadfile(uint64_t *marks, int howto)
dev_t bootdev = bootdev_dip->bootdev;
size_t ac = BOOTARG_LEN;
caddr_t av = (caddr_t)BOOTARG_OFF;
-   bios_consdev_t cd;
+   bios_oconsdev_t cd;
extern int com_speed; /* from bioscons.c */
extern int com_addr;
bios_ddb_t ddb;



Re: amd64 serial console changes

2022-06-30 Thread Anton Lindqvist
On Thu, Jun 30, 2022 at 08:52:33AM +0200, Hrvoje Popovski wrote:
> On 27.6.2022. 23:44, Mark Kettenis wrote:
> > The Ryzen Embedded V1000 processors have an arm64-style Synposys
> > DesignWare UART instead if a PC-compatible NS16x50 UART.  To make this
> > UART work as a serial console, we need to pass some more information
> > from the bootloader to the kernel.  This diff adds the logic to handle
> > that information to the kernel.  I'd like some folks that use a serial
> > console on their amd64 machines to test this.  But testing this diff
> > on amd64 machines with a glass console doesn't hurt.
> > 
> > Thanks,
> > 
> > Mark
> 
> 
> Hi,
> 
> I've sysupgrade few boxes few minutes ago and booting output is quite
> slow. Everything is working but console output needs cca 2 or 3 minutes
> to finish depends how big is dmesg.
> 
> I have few console over ipmi and few connected to serial and all of them
> are slow.
> 
> When boot output finish working over console backs to normal fast output.

I would guess the problem arises after running installboot causing the
new bios_consdev_t structure to be used, whereas only the fields in the
old bios_oconsdev_t structure are populated? Maybe the rename should
have been the other way around until the new structure is populated.

This makes the boot output "fast" again on my machine. I missed
installboot while testing the original diff.

diff --git sys/arch/amd64/stand/libsa/exec_i386.c 
sys/arch/amd64/stand/libsa/exec_i386.c
index 22067931829..25d20d359c0 100644
--- sys/arch/amd64/stand/libsa/exec_i386.c
+++ sys/arch/amd64/stand/libsa/exec_i386.c
@@ -91,7 +91,7 @@ run_loadfile(uint64_t *marks, int howto)
dev_t bootdev = bootdev_dip->bootdev;
size_t ac = BOOTARG_LEN;
caddr_t av = (caddr_t)BOOTARG_OFF;
-   bios_consdev_t cd;
+   bios_oconsdev_t cd;
extern int com_speed; /* from bioscons.c */
extern int com_addr;
bios_ddb_t ddb;



com at acpi: minor nit

2022-06-27 Thread Anton Lindqvist
Hi,
A com_acpi_softc pointer is used as the interrupt callback cookie which
is later on interpreted as a com_softc pointer. This is not a problem in
practice as a com_softc structure is the first member of the
com_acpi_softc structure.

Using the actual types consistently yields a better symmetry in my
opinion between registering the interrupt and the corresponding
interrupt handler.

Comments? OK?

diff --git sys/dev/acpi/com_acpi.c sys/dev/acpi/com_acpi.c
index 9c1e4af0426..b9f2a14edd3 100644
--- sys/dev/acpi/com_acpi.c
+++ sys/dev/acpi/com_acpi.c
@@ -159,9 +159,9 @@ com_acpi_is_designware(const char *hid)
 int
 com_acpi_intr_designware(void *cookie)
 {
-   struct com_softc *sc = cookie;
+   struct com_acpi_softc *sc = cookie;
 
-   com_read_reg(sc, com_usr);
+   com_read_reg(>sc, com_usr);
 
-   return comintr(sc);
+   return comintr(>sc);
 }



bcmdmac: minor nit

2022-06-27 Thread Anton Lindqvist
Hi,
No need to pass a copy of the bcmdmac_channel structure to predicate
routines.

Comments? OK?

diff --git sys/dev/fdt/bcm2835_dmac.c sys/dev/fdt/bcm2835_dmac.c
index 145810dd7af..e9b31af568c 100644
--- sys/dev/fdt/bcm2835_dmac.c
+++ sys/dev/fdt/bcm2835_dmac.c
@@ -97,18 +97,18 @@ struct cfdriver bcmdmac_cd = { NULL, "bcmdmac", DV_DULL };
 
 /* utilities */
 enum bcmdmac_type
-bcmdmac_channel_type(struct bcmdmac_channel ch)
+bcmdmac_channel_type(struct bcmdmac_channel *ch)
 {
-   if (ISSET(ch.ch_debug, DMAC_DEBUG_LITE))
+   if (ISSET(ch->ch_debug, DMAC_DEBUG_LITE))
return BCMDMAC_TYPE_LITE;
else
return BCMDMAC_TYPE_NORMAL;
 }
 
 int
-bcmdmac_channel_used(struct bcmdmac_channel ch)
+bcmdmac_channel_used(struct bcmdmac_channel *ch)
 {
-   return ch.ch_callback != NULL;
+   return ch->ch_callback != NULL;
 }
 
 void
@@ -233,9 +233,9 @@ bcmdmac_alloc(enum bcmdmac_type type, int ipl,
for (index = 0; index < sc->sc_nchannels; index++) {
if (!ISSET(sc->sc_channelmask, (1 << index)))
continue;
-   if (bcmdmac_channel_type(sc->sc_channels[index]) != type)
+   if (bcmdmac_channel_type(>sc_channels[index]) != type)
continue;
-   if (bcmdmac_channel_used(sc->sc_channels[index]))
+   if (bcmdmac_channel_used(>sc_channels[index]))
continue;
 
ch = >sc_channels[index];



Re: pluart(4): change baud rate

2022-06-20 Thread Anton Lindqvist
On Mon, Jun 20, 2022 at 02:42:52PM +, Visa Hankala wrote:
> On Sun, Jun 19, 2022 at 03:06:47PM +0200, Anton Lindqvist wrote:
> > This allows the pluart baud rate to be changed. There's one potential
> > pitfall with this change as users will have the wrong baud rate in their
> > /etc/ttys if not installed after revision 1.11 of dev/ic/pluart.c which
> > landed today. This will make the serial console unusable until the
> > expected baud rate in /etc/ttys is changed to 115200.
> 
> An upgrade note would be good.

I can prepare something for current.html.

> > Comments? OK?
> > 
> > diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
> > index 969018eccdc..ac2467bdf47 100644
> > --- sys/dev/fdt/pluart_fdt.c
> > +++ sys/dev/fdt/pluart_fdt.c
> > @@ -27,6 +27,7 @@
> >  
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  
> >  intpluart_fdt_match(struct device *, void *, void *);
> > @@ -70,8 +71,12 @@ pluart_fdt_attach(struct device *parent, struct device 
> > *self, void *aux)
> > return;
> > }
> >  
> > -   if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart"))
> > +   if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart")) {
> > sc->sc_hwflags |= COM_HW_SBSA;
> > +   } else {
> > +   clock_enable_all(faa->fa_node);
> > +   sc->sc_clkfreq = clock_get_frequency(faa->fa_node, "uartclk");
> > +   }
> >  
> > periphid = OF_getpropint(faa->fa_node, "arm,primecell-periphid", 0);
> > if (periphid != 0)
> > diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
> > index 40e2b1976fb..aa4301e8fb0 100644
> > --- sys/dev/ic/pluart.c
> > +++ sys/dev/ic/pluart.c
> > @@ -71,9 +71,9 @@
> >  #define UART_ILPR  0x20/* IrDA low-power counter 
> > register */
> >  #define UART_ILPR_ILPDVSR  ((x) & 0xf) /* IrDA low-power divisor */
> >  #define UART_IBRD  0x24/* Integer baud rate register */
> > -#define UART_IBRD_DIVINT   ((x) & 0xff)/* Integer baud rate divisor */
> > +#define UART_IBRD_DIVINT(x)((x) & 0xff)/* Integer baud rate 
> > divisor */
> 
> This mask should be 0x.

Thanks, fixed.

> >  #define UART_FBRD  0x28/* Fractional baud rate 
> > register */
> > -#define UART_FBRD_DIVFRAC  ((x) & 0x3f)/* Fractional baud rate divisor 
> > */
> > +#define UART_FBRD_DIVFRAC(x)   ((x) & 0x3f)/* Fractional baud rate 
> > divisor */
> >  #define UART_LCR_H 0x2c/* Line control register */
> >  #define UART_LCR_H_BRK (1 << 0)/* Send break */
> >  #define UART_LCR_H_PEN (1 << 1)/* Parity enable */
> > @@ -338,7 +338,9 @@ pluart_param(struct tty *tp, struct termios *t)
> > /* lower dtr */
> > }
> >  
> > -   if (ospeed != 0) {
> > +   if (ospeed != 0 && sc->sc_clkfreq != 0 && tp->t_ospeed != ospeed) {
> > +   int div, lcr;
> > +
> > while (ISSET(tp->t_state, TS_BUSY)) {
> > ++sc->sc_halt;
> > error = ttysleep(tp, >t_outq,
> > @@ -349,7 +351,40 @@ pluart_param(struct tty *tp, struct termios *t)
> > return (error);
> > }
> > }
> > -   /* set speed */
> > +
> > +   /*
> > +* Writes to IBRD and FBRD are made effective first when LCR_H
> > +* is written.
> > +*/
> > +   lcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H);
> > +
> > +   /* The UART must be disabled while changing the baud rate. */
> > +   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR, 0);
> 
> I think this should save original CR for restoring later, and set CR
> with UARTEN masked out.
> 
>   cr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_CR);
>   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR,
>   cr & ~UART_CR_UARTEN);
> 
> The PL011 manual says that reserved bits in CR should not be modified.
> 
> > +
> > +   /*
> > +* The baud rate divisor is expressed relative to the UART clock
> > +* frequency where IBRD represents the quotient using 16 bits
> > +* and FBRD the remainder using 6 bits. The PL011 specification
> >

pluart(4): change baud rate

2022-06-19 Thread Anton Lindqvist
Hi,
This allows the pluart baud rate to be changed. There's one potential
pitfall with this change as users will have the wrong baud rate in their
/etc/ttys if not installed after revision 1.11 of dev/ic/pluart.c which
landed today. This will make the serial console unusable until the
expected baud rate in /etc/ttys is changed to 115200.

Comments? OK?

diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
index 969018eccdc..ac2467bdf47 100644
--- sys/dev/fdt/pluart_fdt.c
+++ sys/dev/fdt/pluart_fdt.c
@@ -27,6 +27,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 intpluart_fdt_match(struct device *, void *, void *);
@@ -70,8 +71,12 @@ pluart_fdt_attach(struct device *parent, struct device 
*self, void *aux)
return;
}
 
-   if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart"))
+   if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart")) {
sc->sc_hwflags |= COM_HW_SBSA;
+   } else {
+   clock_enable_all(faa->fa_node);
+   sc->sc_clkfreq = clock_get_frequency(faa->fa_node, "uartclk");
+   }
 
periphid = OF_getpropint(faa->fa_node, "arm,primecell-periphid", 0);
if (periphid != 0)
diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
index 40e2b1976fb..aa4301e8fb0 100644
--- sys/dev/ic/pluart.c
+++ sys/dev/ic/pluart.c
@@ -71,9 +71,9 @@
 #define UART_ILPR  0x20/* IrDA low-power counter 
register */
 #define UART_ILPR_ILPDVSR  ((x) & 0xf) /* IrDA low-power divisor */
 #define UART_IBRD  0x24/* Integer baud rate register */
-#define UART_IBRD_DIVINT   ((x) & 0xff)/* Integer baud rate divisor */
+#define UART_IBRD_DIVINT(x)((x) & 0xff)/* Integer baud rate divisor */
 #define UART_FBRD  0x28/* Fractional baud rate 
register */
-#define UART_FBRD_DIVFRAC  ((x) & 0x3f)/* Fractional baud rate divisor 
*/
+#define UART_FBRD_DIVFRAC(x)   ((x) & 0x3f)/* Fractional baud rate divisor 
*/
 #define UART_LCR_H 0x2c/* Line control register */
 #define UART_LCR_H_BRK (1 << 0)/* Send break */
 #define UART_LCR_H_PEN (1 << 1)/* Parity enable */
@@ -338,7 +338,9 @@ pluart_param(struct tty *tp, struct termios *t)
/* lower dtr */
}
 
-   if (ospeed != 0) {
+   if (ospeed != 0 && sc->sc_clkfreq != 0 && tp->t_ospeed != ospeed) {
+   int div, lcr;
+
while (ISSET(tp->t_state, TS_BUSY)) {
++sc->sc_halt;
error = ttysleep(tp, >t_outq,
@@ -349,7 +351,40 @@ pluart_param(struct tty *tp, struct termios *t)
return (error);
}
}
-   /* set speed */
+
+   /*
+* Writes to IBRD and FBRD are made effective first when LCR_H
+* is written.
+*/
+   lcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H);
+
+   /* The UART must be disabled while changing the baud rate. */
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR, 0);
+
+   /*
+* The baud rate divisor is expressed relative to the UART clock
+* frequency where IBRD represents the quotient using 16 bits
+* and FBRD the remainder using 6 bits. The PL011 specification
+* provides the following formula:
+*
+*  uartclk/(16 * baudrate)
+*
+* The formula can be estimated by scaling it with the
+* precision 64 (2^6) and letting the resulting upper 16 bits
+* represents the quotient and the lower 6 bits the remainder:
+*
+*  64 * uartclk/(16 * baudrate) = 4 * uartclk/baudrate
+*/
+   div = 4 * sc->sc_clkfreq / ospeed;
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IBRD,
+   UART_IBRD_DIVINT(div >> 6));
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_FBRD,
+   UART_FBRD_DIVFRAC(div));
+   /* Commit baud rate change. */
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H, lcr);
+   /* Enable UART. */
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+   UART_CR, UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE);
}
 
/* setup fifo */
@@ -594,13 +629,6 @@ pluartopen(dev_t dev, int flag, int mode, struct proc *p)
5 << IMXUART_FCR_RFDIV_SH |
1 << IMXUART_FCR_RXTL_SH);
 
-   bus_space_write_4(iot, ioh, IMXUART_UBIR,
-   (pluartdefaultrate / 100) - 1);
-
-   /* formula: clk / (rfdiv * 1600) */
-   bus_space_write_4(iot, ioh, IMXUART_UBMR,
-   (clk_get_rate(sc->sc_clk) * 1000) / 1600);
-
 

pluart(4): hardware console baudrate

2022-06-14 Thread Anton Lindqvist
Hi,
pluart(4) does not report the correct baudrate for the hardware console
but instead defaults to 38400. This in turn causes the same baudrate to
end up in /etc/ttys during installation. Note that this is not a problem
as of now since pluart does not support changing the baudrate just yet,
I have another subsequent diff for that.

Instead, honor and propagate the baudrate given to pluartcnattach()
while attaching the hardware console. Similar to what com(4) already
does.

Comments? OK?

diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
index be7d4483646..03acab832a9 100644
--- sys/dev/ic/pluart.c
+++ sys/dev/ic/pluart.c
@@ -153,11 +153,12 @@ struct cfdriver pluart_cd = {
NULL, "pluart", DV_TTY
 };
 
+intpluartdefaultrate = B38400;
+intpluartconsrate = B38400;
 bus_space_tag_tpluartconsiot;
 bus_space_handle_t pluartconsioh;
 bus_addr_t pluartconsaddr;
 tcflag_t   pluartconscflag = TTYDEF_CFLAG;
-intpluartdefaultrate = B38400;
 
 struct cdevsw pluartdev =
cdev_tty_init(3/*XXX NUART */ ,pluart); /* 12: serial port */
@@ -563,7 +564,10 @@ pluartopen(dev_t dev, int flag, int mode, struct proc *p)
if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
SET(tp->t_cflag, MDMBUF);
tp->t_lflag = TTYDEF_LFLAG;
-   tp->t_ispeed = tp->t_ospeed = pluartdefaultrate;
+   if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+   tp->t_ispeed = tp->t_ospeed = pluartconsrate;
+   else
+   tp->t_ispeed = tp->t_ospeed = pluartdefaultrate;
 
s = spltty();
 
@@ -837,6 +841,7 @@ pluartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int 
rate, tcflag_t cflag)
pluartconsiot = iot;
pluartconsaddr = iobase;
pluartconscflag = cflag;
+   pluartconsrate = rate;
 
return 0;
 }



Re: pluart(4): fifo support

2022-06-10 Thread Anton Lindqvist
On Fri, Jun 10, 2022 at 01:15:12PM +, Visa Hankala wrote:
> On Wed, Jun 08, 2022 at 06:50:18AM +0200, Anton Lindqvist wrote:
> > On Sun, May 01, 2022 at 04:17:34PM +, Visa Hankala wrote:
> > > On Sat, Apr 30, 2022 at 09:40:24AM +0200, Anton Lindqvist wrote:
> > > > On Sun, Mar 13, 2022 at 04:17:07PM +0100, Mark Kettenis wrote:
> > > > > > Date: Fri, 11 Mar 2022 07:53:13 +0100
> > > > > > From: Anton Lindqvist 
> > > > > > 
> > > > > > On Tue, Mar 08, 2022 at 01:44:47PM +, Visa Hankala wrote:
> > > > > > > On Tue, Mar 08, 2022 at 08:04:36AM +0100, Anton Lindqvist wrote:
> > > > > > > > On Mon, Mar 07, 2022 at 07:36:35AM +, Visa Hankala wrote:
> > > > > > > > > I still think that checking TXFF and using the same code for 
> > > > > > > > > both
> > > > > > > > > SBSA and true PL011 UARTs would be the best choice. This 
> > > > > > > > > would avoid
> > > > > > > > > fragmenting the code and improve robustness by relying on 
> > > > > > > > > functionality
> > > > > > > > > that is common to the different controller variants.
> > > > > > > > 
> > > > > > > > Fair enough, new diff.
> > > > > > > 
> > > > > > > Maybe the comments should omit the FIFO space description and just
> > > > > > > mention the lack of the level control register in the SBSA UART
> > > > > > > register interface.
> > > > > > 
> > > > > > I ended up tweaking the comments before committing. Thanks for all 
> > > > > > the
> > > > > > feedback.
> > > > > > 
> > > > > 
> > > > > Hi Anton,
> > > > > 
> > > > > This diff seems to break things.  When I boot my rpi4 it now prints:
> > > > > 
> > > > >   pluart0 at simplebus0: rev 0, 16 byte fifo
> > > > >   pluart0: console
> > > > >   bcmbsc0 at simplebus0
> > > > >   iic0 at bcmbsc0
> > > > > 
> > > > > so it appears that a carriage return character is lost here.
> > > > > 
> > > > > Later on output stops at:
> > > > > 
> > > > >   reordering libraries: done.
> > > > > 
> > > > > and only when I reboot the machine the login prompt appears, but with
> > > > > some wierd respawning:
> > > > > 
> > > > >   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> > > > > 
> > > > >   login: init: getty repeating too quickly on port /dev/console, 
> > > > > sleeping
> > > > >   init: getty repeating too quickly on port /dev/console, sleeping
> > > > > 
> > > > >   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> > > > > 
> > > > >   login:
> > > > >   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> > > > > 
> > > > >   login:
> > > > > 
> > > > > If you don't have a quick fix for this, may I suggest reverting the
> > > > > commit?  We're heading towards release and we don't want the serial
> > > > > console on the rpi4 to be broken.
> > > > 
> > > > Circling back to this: what happens is that no tx interrupt is raised
> > > > when sending less data than the configured interrupt fifo level, causing
> > > > the tty to end up in a forever busy state. Clearing the busy flag after
> > > > a successful transmission of all queued data solves the problem.
> > > 
> > > Are you sure about the behaviour of the interrupt?
> > > 
> > > One possible problem is that pluart_intr() uses the raw, unmasked,
> > > interrupt status to clear interrupts. Your previous patch always
> > > disabled the Tx interrupt whenever the raw status indicated a Tx FIFO
> > > level event.
> > > 
> > > This new patch might very well be correct. However, it feels strange
> > > if the hardware raises the Tx interrupt only at one specific level of
> > > FIFO state change.
> > > 
> > > It would be nice to know if a comstart()-style arrangement of interrupt
> > > masking worked in pluart_start().
> > 
> > What did work was to not clear the tx interrupt in pluart_intr().
> > Updated diff with some additional changes:
> > 
> > * Flush any pending transmission before configuring the device during
> >   attachment. Prevents the next dmesg line from being mangled.
> > 
> > * Make pluart_start() mimic comstart() as proposed by visa@.
> > 
> > * While entering ddb (i.e. poll mode), disable interrupts.
> 
> 
> 
> > @@ -792,4 +870,13 @@ pluartcnputc(dev_t dev, int c)
> >  void
> >  pluartcnpollc(dev_t dev, int on)
> >  {
> > +   int s;
> > +
> > +   s = splhigh();
> > +   if (on)
> > +   bus_space_write_4(pluartconsiot, pluartconsioh, UART_IMSC, 0);
> > +   else
> > +   bus_space_write_4(pluartconsiot, pluartconsioh, UART_IMSC,
> > +   UART_IMSC_RXIM | UART_IMSC_RTIM);
> > +   splx(s);
> >  }
> 
> Does this fix an actual issue? If not, I would leave it out. ddb entry
> can happen in unexpected places. There is a risk that the mask gets
> messed up in particular when leaving the debugger.

It's not. I will drop this chunk before getting this committed.



Re: pluart(4): fifo support

2022-06-07 Thread Anton Lindqvist
On Sun, May 01, 2022 at 04:17:34PM +, Visa Hankala wrote:
> On Sat, Apr 30, 2022 at 09:40:24AM +0200, Anton Lindqvist wrote:
> > On Sun, Mar 13, 2022 at 04:17:07PM +0100, Mark Kettenis wrote:
> > > > Date: Fri, 11 Mar 2022 07:53:13 +0100
> > > > From: Anton Lindqvist 
> > > > 
> > > > On Tue, Mar 08, 2022 at 01:44:47PM +, Visa Hankala wrote:
> > > > > On Tue, Mar 08, 2022 at 08:04:36AM +0100, Anton Lindqvist wrote:
> > > > > > On Mon, Mar 07, 2022 at 07:36:35AM +, Visa Hankala wrote:
> > > > > > > I still think that checking TXFF and using the same code for both
> > > > > > > SBSA and true PL011 UARTs would be the best choice. This would 
> > > > > > > avoid
> > > > > > > fragmenting the code and improve robustness by relying on 
> > > > > > > functionality
> > > > > > > that is common to the different controller variants.
> > > > > > 
> > > > > > Fair enough, new diff.
> > > > > 
> > > > > Maybe the comments should omit the FIFO space description and just
> > > > > mention the lack of the level control register in the SBSA UART
> > > > > register interface.
> > > > 
> > > > I ended up tweaking the comments before committing. Thanks for all the
> > > > feedback.
> > > > 
> > > 
> > > Hi Anton,
> > > 
> > > This diff seems to break things.  When I boot my rpi4 it now prints:
> > > 
> > >   pluart0 at simplebus0: rev 0, 16 byte fifo
> > >   pluart0: console
> > >   bcmbsc0 at simplebus0
> > >   iic0 at bcmbsc0
> > > 
> > > so it appears that a carriage return character is lost here.
> > > 
> > > Later on output stops at:
> > > 
> > >   reordering libraries: done.
> > > 
> > > and only when I reboot the machine the login prompt appears, but with
> > > some wierd respawning:
> > > 
> > >   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> > > 
> > >   login: init: getty repeating too quickly on port /dev/console, sleeping
> > >   init: getty repeating too quickly on port /dev/console, sleeping
> > > 
> > >   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> > > 
> > >   login:
> > >   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> > > 
> > >   login:
> > > 
> > > If you don't have a quick fix for this, may I suggest reverting the
> > > commit?  We're heading towards release and we don't want the serial
> > > console on the rpi4 to be broken.
> > 
> > Circling back to this: what happens is that no tx interrupt is raised
> > when sending less data than the configured interrupt fifo level, causing
> > the tty to end up in a forever busy state. Clearing the busy flag after
> > a successful transmission of all queued data solves the problem.
> 
> Are you sure about the behaviour of the interrupt?
> 
> One possible problem is that pluart_intr() uses the raw, unmasked,
> interrupt status to clear interrupts. Your previous patch always
> disabled the Tx interrupt whenever the raw status indicated a Tx FIFO
> level event.
> 
> This new patch might very well be correct. However, it feels strange
> if the hardware raises the Tx interrupt only at one specific level of
> FIFO state change.
> 
> It would be nice to know if a comstart()-style arrangement of interrupt
> masking worked in pluart_start().

What did work was to not clear the tx interrupt in pluart_intr().
Updated diff with some additional changes:

* Flush any pending transmission before configuring the device during
  attachment. Prevents the next dmesg line from being mangled.

* Make pluart_start() mimic comstart() as proposed by visa@.

* While entering ddb (i.e. poll mode), disable interrupts.

diff --git sys/dev/acpi/pluart_acpi.c sys/dev/acpi/pluart_acpi.c
index e90e810e76f..284769d159e 100644
--- sys/dev/acpi/pluart_acpi.c
+++ sys/dev/acpi/pluart_acpi.c
@@ -91,6 +91,8 @@ pluart_acpi_attach(struct device *parent, struct device 
*self, void *aux)
return;
}
 
+   sc->sc.sc_hwflags |= COM_HW_SBSA;
+
pluart_attach_common(>sc, pluart_acpi_is_console(sc));
 }
 
diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
index 7be34b37f19..a1d7e006f39 100644
--- sys/dev/fdt/pluart_fdt.c
+++ sys/dev/fdt/pluart_fdt.c
@@ -63,12 +63,20 @@ pluart_fdt_attach(struct device *parent, struct device 
*self, void *aux)
 {
struct fdt_attach_args *faa =

usb: another bad hid quirk

2022-06-02 Thread Anton Lindqvist
Hi,
I recently got a Gembird EG-PMS2 power strip controllable over USB.
It currently attaches over uhidev which is problematic since it lacks an
interrupt endpoint causing uhidev to punt early during attachment.
Instead, letting it attach as ugen makes it possible to control the
device using third-party software like sispmctl.

Here's a diff adding a quirk, excluding the usbdevs regen bits.

Comments? OK?

diff --git sys/dev/usb/usb_quirks.c sys/dev/usb/usb_quirks.c
index be65ad08602..a85ea0cd510 100644
--- sys/dev/usb/usb_quirks.c
+++ sys/dev/usb/usb_quirks.c
@@ -126,6 +126,7 @@ const struct usbd_quirk_entry {
  { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_SISPM_OLD,  ANY,{ UQ_BAD_HID }},
  { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_SISPM,  ANY,{ UQ_BAD_HID }},
  { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_SISPM_FLASH,ANY,{ 
UQ_BAD_HID }},
+ { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_GEMBIRD_EG_PMS2,ANY,{ 
UQ_BAD_HID }},
  { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_USBLCD20X2, ANY,{ 
UQ_BAD_HID }},
  { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_USBLCD256X64,   ANY,{ 
UQ_BAD_HID }},
  { USB_VENDOR_MECANIQUE, USB_PRODUCT_MECANIQUE_WISPY,  ANY,{ UQ_BAD_HID }},
diff --git sys/dev/usb/usbdevs sys/dev/usb/usbdevs
index 1091754f576..6cbf022bba4 100644
--- sys/dev/usb/usbdevs
+++ sys/dev/usb/usbdevs
@@ -1508,6 +1508,7 @@ product CYPRESS LPRDK 0xe001  CY4636 LP RDK 
Bridge
 product CYPRESS SISPM_OLD  0xfd10  Sispm - old version
 product CYPRESS SISPM  0xfd11  Sispm
 product CYPRESS SISPM_FLASH0xfd12  Sispm - flash
+product CYPRESS GEMBIRD_EG_PMS20xfd15  Gembird EG-PMS2
 
 /* Daisy Technology products */
 product DAISY DMC  0x6901  PhotoClip



Re: pluart(4): fifo support

2022-04-30 Thread Anton Lindqvist
On Sun, Mar 13, 2022 at 04:17:07PM +0100, Mark Kettenis wrote:
> > Date: Fri, 11 Mar 2022 07:53:13 +0100
> > From: Anton Lindqvist 
> > 
> > On Tue, Mar 08, 2022 at 01:44:47PM +, Visa Hankala wrote:
> > > On Tue, Mar 08, 2022 at 08:04:36AM +0100, Anton Lindqvist wrote:
> > > > On Mon, Mar 07, 2022 at 07:36:35AM +, Visa Hankala wrote:
> > > > > I still think that checking TXFF and using the same code for both
> > > > > SBSA and true PL011 UARTs would be the best choice. This would avoid
> > > > > fragmenting the code and improve robustness by relying on 
> > > > > functionality
> > > > > that is common to the different controller variants.
> > > > 
> > > > Fair enough, new diff.
> > > 
> > > Maybe the comments should omit the FIFO space description and just
> > > mention the lack of the level control register in the SBSA UART
> > > register interface.
> > 
> > I ended up tweaking the comments before committing. Thanks for all the
> > feedback.
> > 
> 
> Hi Anton,
> 
> This diff seems to break things.  When I boot my rpi4 it now prints:
> 
>   pluart0 at simplebus0: rev 0, 16 byte fifo
>   pluart0: console
>   bcmbsc0 at simplebus0
>   iic0 at bcmbsc0
> 
> so it appears that a carriage return character is lost here.
> 
> Later on output stops at:
> 
>   reordering libraries: done.
> 
> and only when I reboot the machine the login prompt appears, but with
> some wierd respawning:
> 
>   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> 
>   login: init: getty repeating too quickly on port /dev/console, sleeping
>   init: getty repeating too quickly on port /dev/console, sleeping
> 
>   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> 
>   login:
>   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> 
>   login:
> 
> If you don't have a quick fix for this, may I suggest reverting the
> commit?  We're heading towards release and we don't want the serial
> console on the rpi4 to be broken.

Circling back to this: what happens is that no tx interrupt is raised
when sending less data than the configured interrupt fifo level, causing
the tty to end up in a forever busy state. Clearing the busy flag after
a successful transmission of all queued data solves the problem.

While here, the hardware revision in the optional arm,primecell-periphid
fdt node have higher precedence.

Testing would be much appreciated.

diff --git sys/dev/acpi/pluart_acpi.c sys/dev/acpi/pluart_acpi.c
index e90e810e76f..284769d159e 100644
--- sys/dev/acpi/pluart_acpi.c
+++ sys/dev/acpi/pluart_acpi.c
@@ -91,6 +91,8 @@ pluart_acpi_attach(struct device *parent, struct device 
*self, void *aux)
return;
}
 
+   sc->sc.sc_hwflags |= COM_HW_SBSA;
+
pluart_attach_common(>sc, pluart_acpi_is_console(sc));
 }
 
diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
index 7be34b37f19..a1d7e006f39 100644
--- sys/dev/fdt/pluart_fdt.c
+++ sys/dev/fdt/pluart_fdt.c
@@ -63,12 +63,20 @@ pluart_fdt_attach(struct device *parent, struct device 
*self, void *aux)
 {
struct fdt_attach_args *faa = aux;
struct pluart_softc *sc = (struct pluart_softc *) self;
+   uint32_t periphid;
 
if (faa->fa_nreg < 1) {
printf(": no registers\n");
return;
}
 
+   if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart"))
+   sc->sc_hwflags |= COM_HW_SBSA;
+
+   periphid = OF_getpropint(faa->fa_node, "arm,primecell-periphid", 0);
+   if (periphid != 0)
+   sc->sc_hwrev = (periphid >> 20) & 0x0f;
+
sc->sc_irq = fdt_intr_establish(faa->fa_node, IPL_TTY, pluart_intr,
sc, sc->sc_dev.dv_xname);
 
diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
index 8a2b512eaeb..69654426a34 100644
--- sys/dev/ic/pluart.c
+++ sys/dev/ic/pluart.c
@@ -99,6 +99,13 @@
 #define UART_CR_CTSE   (1 << 14)   /* CTS hardware flow control 
enable */
 #define UART_CR_RTSE   (1 << 15)   /* RTS hardware flow control 
enable */
 #define UART_IFLS  0x34/* Interrupt FIFO level select 
register */
+#define UART_IFLS_RX_SHIFT 3   /* RX level in bits [5:3] */
+#define UART_IFLS_TX_SHIFT 0   /* TX level in bits [2:0] */
+#define UART_IFLS_1_8  0   /* FIFO 1/8 full */
+#define UART_IFLS_1_4  1   /* FIFO 1/4 full */
+#define UART_IFLS_1_2  2   /* FIFO 1/2 full */
+#define UART_IFLS_3_4  3   /* FIFO 3/4 full */
+#define UART_IFLS_7_8  4   /* FIFO 7/8 full */
 #define UAR

Re: pluart(4): fifo support

2022-03-13 Thread Anton Lindqvist
On Sun, Mar 13, 2022 at 04:17:07PM +0100, Mark Kettenis wrote:
> > Date: Fri, 11 Mar 2022 07:53:13 +0100
> > From: Anton Lindqvist 
> > 
> > On Tue, Mar 08, 2022 at 01:44:47PM +, Visa Hankala wrote:
> > > On Tue, Mar 08, 2022 at 08:04:36AM +0100, Anton Lindqvist wrote:
> > > > On Mon, Mar 07, 2022 at 07:36:35AM +, Visa Hankala wrote:
> > > > > I still think that checking TXFF and using the same code for both
> > > > > SBSA and true PL011 UARTs would be the best choice. This would avoid
> > > > > fragmenting the code and improve robustness by relying on 
> > > > > functionality
> > > > > that is common to the different controller variants.
> > > > 
> > > > Fair enough, new diff.
> > > 
> > > Maybe the comments should omit the FIFO space description and just
> > > mention the lack of the level control register in the SBSA UART
> > > register interface.
> > 
> > I ended up tweaking the comments before committing. Thanks for all the
> > feedback.
> > 
> 
> Hi Anton,
> 
> This diff seems to break things.  When I boot my rpi4 it now prints:
> 
>   pluart0 at simplebus0: rev 0, 16 byte fifo
>   pluart0: console
>   bcmbsc0 at simplebus0
>   iic0 at bcmbsc0
> 
> so it appears that a carriage return character is lost here.
> 
> Later on output stops at:
> 
>   reordering libraries: done.
> 
> and only when I reboot the machine the login prompt appears, but with
> some wierd respawning:
> 
>   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> 
>   login: init: getty repeating too quickly on port /dev/console, sleeping
>   init: getty repeating too quickly on port /dev/console, sleeping
> 
>   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> 
>   login:
>   OpenBSD/arm64 (rutter.sibelius.xs4all.nl) (console)
> 
>   login:
> 
> If you don't have a quick fix for this, may I suggest reverting the
> commit?  We're heading towards release and we don't want the serial
> console on the rpi4 to be broken.

I don't have a quick fix. I'm not able to revert until Tuesday, could
you or anyone else go ahead and revert the commit? Would be much
appreciated.



Re: pluart(4): fifo support

2022-03-10 Thread Anton Lindqvist
On Tue, Mar 08, 2022 at 01:44:47PM +, Visa Hankala wrote:
> On Tue, Mar 08, 2022 at 08:04:36AM +0100, Anton Lindqvist wrote:
> > On Mon, Mar 07, 2022 at 07:36:35AM +, Visa Hankala wrote:
> > > I still think that checking TXFF and using the same code for both
> > > SBSA and true PL011 UARTs would be the best choice. This would avoid
> > > fragmenting the code and improve robustness by relying on functionality
> > > that is common to the different controller variants.
> > 
> > Fair enough, new diff.
> 
> Maybe the comments should omit the FIFO space description and just
> mention the lack of the level control register in the SBSA UART
> register interface.

I ended up tweaking the comments before committing. Thanks for all the
feedback.



Re: pluart(4): fifo support

2022-03-07 Thread Anton Lindqvist
On Mon, Mar 07, 2022 at 07:36:35AM +, Visa Hankala wrote:
> On Wed, Mar 02, 2022 at 07:25:36AM +0100, Anton Lindqvist wrote:
> > On Tue, Mar 01, 2022 at 01:41:10PM +, Visa Hankala wrote:
> > > On Tue, Mar 01, 2022 at 07:08:51AM +0100, Anton Lindqvist wrote:
> > > > On Sun, Feb 27, 2022 at 05:33:17PM +0100, Mark Kettenis wrote:
> > > > > > Date: Sun, 27 Feb 2022 16:01:25 +0100
> > > > > > From: Anton Lindqvist 
> > > > > > 
> > > 
> > > > > > r1p5 is revision 3 with a 32 bytes FIFO. My only concern is that the
> > > > > > following registers which this diff makes use of are not enumerated 
> > > > > > in
> > > > > > the "Base UART Register Set" listing:
> > > > > > 
> > > > > > 1. UARTPeriphID2 - used to deduce the revision
> > > > > > 2. UARTIFLS - interrupt FIFO level select register
> > > > > 
> > > > > Right.  So you can't really use those registers, at least not
> > > > > unconditionally.
> > > > > 
> > > > > What we could do is add a flag to the softc to indicate that we're
> > > > > dealing with an SBSA UART instead of a genuine PL011 UART.  This would
> > > > > skip reading the UARTPeriphID2 (assuming r1p5 properties) and skip
> > > > > touching UARTIFLS (and perhaps some other potentially unimplemented
> > > > > registers).
> > > > > 
> > > > > We would set this flag based on the compatible string in pluart_fdt.c
> > > > > and based on the _HID (or maybe even unconditionally) in
> > > > > pluart_acpi.c.
> > > > 
> > > > Here's a first stab at handling such devices. Attaching over ACPI also
> > > > keeps the FIFO disabled.
> > > > 
> > > > diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
> > > > index 7f17365f1d6..45e31f9872f 100644
> > > > --- sys/dev/fdt/pluart_fdt.c
> > > > +++ sys/dev/fdt/pluart_fdt.c
> > > > @@ -69,6 +69,16 @@ pluart_fdt_attach(struct device *parent, struct 
> > > > device *self, void *aux)
> > > > return;
> > > > }
> > > >  
> > > > +   /*
> > > > +* The SBSA UART is PL011 r1p5 compliant which implies revision 
> > > > 3 with a
> > > > +* 32 byte FIFO. However, we cannot expect to configure RX/TX 
> > > > interrupt
> > > > +* levels using the UARTIFLS register making it impossible to 
> > > > make
> > > > +* assumptions about the number of available bytes in the FIFO.
> > > > +* Therefore disable FIFO support for such devices.
> > > > +*/
> > > > +   if (!OF_is_compatible(faa->fa_node, "arm,sbsa-uart"))
> > > > +   sc->sc_hwflags |= COM_HW_FIFO;
> > > > +
> > > 
> > > Could this piece of code use a dedicated flag, say COM_HW_SBSA (or
> > > inversely COM_HW_PL011), that tells that the UART is an SBSA UART (or
> > > true PL011 UART).
> > > 
> > > To me, this use of the COM_HW_FIFO is a bit obscure; you need to look
> > > at the comment in pluart_fdt_attach() to understand the logic.
> > 
> > New diff replacing usage of COM_HW_FIFO with COM_HW_SBSA.
> > 
> > > Is worrying about the exact size of the FIFO really worthwhile? As I
> > > suggested earlier, pluart_start() could check the TXFF flag in the
> > > Flag Register before feeding each byte to the FIFO. This would allow
> > > the same transmit code apply to both SBSA and true PL011 UARTs.
> > > 
> > > The SBSA UART interface does not have the IFLS register. However, it
> > > looks that the FIFO and the interrupt are usable nevertheless. At least
> > > Linux appears to enable them.
> > 
> > I did look at Linux as well. They do not initialize the ifls field for
> > SBSA devices causing 0 to be written to the UARTIFLS register which
> > implies an interrupt level of 1/8 for both RX and TX. However, it's
> > still unknown whenever this have any effect or not.
> 
> I think the Linux driver does not use ifls when setting up
> the SBSA UART. Compare pl011_startup() and sbsa_uart_startup() on Linux.
> 
> > diff --git sys/dev/acpi/pluart_acpi.c sys/dev/acpi/pluart_acpi.c
> > index dc8ea5e9922..08ebe13ffbc 100644
> > --- sys/dev/acpi/pluart_acpi.c
> > +++ sys/dev/acp

Re: pluart(4): fifo support

2022-03-01 Thread Anton Lindqvist
On Tue, Mar 01, 2022 at 01:41:10PM +, Visa Hankala wrote:
> On Tue, Mar 01, 2022 at 07:08:51AM +0100, Anton Lindqvist wrote:
> > On Sun, Feb 27, 2022 at 05:33:17PM +0100, Mark Kettenis wrote:
> > > > Date: Sun, 27 Feb 2022 16:01:25 +0100
> > > > From: Anton Lindqvist 
> > > > 
> 
> > > > r1p5 is revision 3 with a 32 bytes FIFO. My only concern is that the
> > > > following registers which this diff makes use of are not enumerated in
> > > > the "Base UART Register Set" listing:
> > > > 
> > > > 1. UARTPeriphID2 - used to deduce the revision
> > > > 2. UARTIFLS - interrupt FIFO level select register
> > > 
> > > Right.  So you can't really use those registers, at least not
> > > unconditionally.
> > > 
> > > What we could do is add a flag to the softc to indicate that we're
> > > dealing with an SBSA UART instead of a genuine PL011 UART.  This would
> > > skip reading the UARTPeriphID2 (assuming r1p5 properties) and skip
> > > touching UARTIFLS (and perhaps some other potentially unimplemented
> > > registers).
> > > 
> > > We would set this flag based on the compatible string in pluart_fdt.c
> > > and based on the _HID (or maybe even unconditionally) in
> > > pluart_acpi.c.
> > 
> > Here's a first stab at handling such devices. Attaching over ACPI also
> > keeps the FIFO disabled.
> > 
> > diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
> > index 7f17365f1d6..45e31f9872f 100644
> > --- sys/dev/fdt/pluart_fdt.c
> > +++ sys/dev/fdt/pluart_fdt.c
> > @@ -69,6 +69,16 @@ pluart_fdt_attach(struct device *parent, struct device 
> > *self, void *aux)
> > return;
> > }
> >  
> > +   /*
> > +* The SBSA UART is PL011 r1p5 compliant which implies revision 3 with a
> > +* 32 byte FIFO. However, we cannot expect to configure RX/TX interrupt
> > +* levels using the UARTIFLS register making it impossible to make
> > +* assumptions about the number of available bytes in the FIFO.
> > +* Therefore disable FIFO support for such devices.
> > +*/
> > +   if (!OF_is_compatible(faa->fa_node, "arm,sbsa-uart"))
> > +   sc->sc_hwflags |= COM_HW_FIFO;
> > +
> 
> Could this piece of code use a dedicated flag, say COM_HW_SBSA (or
> inversely COM_HW_PL011), that tells that the UART is an SBSA UART (or
> true PL011 UART).
> 
> To me, this use of the COM_HW_FIFO is a bit obscure; you need to look
> at the comment in pluart_fdt_attach() to understand the logic.

New diff replacing usage of COM_HW_FIFO with COM_HW_SBSA.

> Is worrying about the exact size of the FIFO really worthwhile? As I
> suggested earlier, pluart_start() could check the TXFF flag in the
> Flag Register before feeding each byte to the FIFO. This would allow
> the same transmit code apply to both SBSA and true PL011 UARTs.
> 
> The SBSA UART interface does not have the IFLS register. However, it
> looks that the FIFO and the interrupt are usable nevertheless. At least
> Linux appears to enable them.

I did look at Linux as well. They do not initialize the ifls field for
SBSA devices causing 0 to be written to the UARTIFLS register which
implies an interrupt level of 1/8 for both RX and TX. However, it's
still unknown whenever this have any effect or not.

diff --git sys/dev/acpi/pluart_acpi.c sys/dev/acpi/pluart_acpi.c
index dc8ea5e9922..08ebe13ffbc 100644
--- sys/dev/acpi/pluart_acpi.c
+++ sys/dev/acpi/pluart_acpi.c
@@ -91,6 +91,8 @@ pluart_acpi_attach(struct device *parent, struct device 
*self, void *aux)
return;
}
 
+   sc->sc.sc_hwflags |= COM_HW_SBSA;
+
pluart_attach_common(>sc, pluart_acpi_is_console(sc));
 }
 
diff --git sys/dev/fdt/pluart_fdt.c sys/dev/fdt/pluart_fdt.c
index 7f17365f1d6..798250593bf 100644
--- sys/dev/fdt/pluart_fdt.c
+++ sys/dev/fdt/pluart_fdt.c
@@ -69,6 +69,9 @@ pluart_fdt_attach(struct device *parent, struct device *self, 
void *aux)
return;
}
 
+   if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart"))
+   sc->sc_hwflags |= COM_HW_SBSA;
+
sc->sc_irq = fdt_intr_establish(faa->fa_node, IPL_TTY, pluart_intr,
sc, sc->sc_dev.dv_xname);
 
diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
index eaa11b6c44b..61233290e0d 100644
--- sys/dev/ic/pluart.c
+++ sys/dev/ic/pluart.c
@@ -99,6 +99,13 @@
 #define UART_CR_CTSE   (1 << 14)   /* CTS hardware flow control 
enable */
 #define UART_CR_RTSE   (1 << 15)   /* RTS hardware flow control 
enable */
 #define UART_IFLS  0x34 

Re: pluart(4): fifo support

2022-02-28 Thread Anton Lindqvist
On Sun, Feb 27, 2022 at 05:33:17PM +0100, Mark Kettenis wrote:
> > Date: Sun, 27 Feb 2022 16:01:25 +0100
> > From: Anton Lindqvist 
> > 
> > On Sun, Feb 27, 2022 at 11:08:14AM +0100, Mark Kettenis wrote:
> > > > Date: Sun, 27 Feb 2022 09:56:38 +0100
> > > > From: Anton Lindqvist 
> > > > 
> > > > On Sun, Feb 27, 2022 at 06:19:02AM +, Visa Hankala wrote:
> > > > > On Sat, Feb 26, 2022 at 08:40:25AM +0100, Anton Lindqvist wrote:
> > > > > > Hi,
> > > > > > This enables fifo support in pluart(4). While here, I changed the
> > > > > > attachment output to look more like com(4). Tested on my rpi3b 
> > > > > > which has
> > > > > > a 16 byte fifo.
> > > > > > 
> > > > > > Comments? OK?
> > > > > > 
> > > > > > diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
> > > > > > index eaa11b6c44b..601435c0e0c 100644
> > > > > > --- sys/dev/ic/pluart.c
> > > > > > +++ sys/dev/ic/pluart.c
> > > > > > @@ -99,6 +99,13 @@
> > > > > >  #define UART_CR_CTSE   (1 << 14)   /* CTS hardware 
> > > > > > flow control enable */
> > > > > >  #define UART_CR_RTSE   (1 << 15)   /* RTS hardware 
> > > > > > flow control enable */
> > > > > >  #define UART_IFLS  0x34/* Interrupt FIFO level 
> > > > > > select register */
> > > > > > +#define UART_IFLS_RX_SHIFT 3   /* RX level in bits 
> > > > > > [5:3] */
> > > > > > +#define UART_IFLS_TX_SHIFT 0   /* TX level in bits 
> > > > > > [2:0] */
> > > > > > +#define UART_IFLS_1_8  0   /* FIFO 1/8 
> > > > > > full */
> > > > > > +#define UART_IFLS_1_4  1   /* FIFO 1/4 
> > > > > > full */
> > > > > > +#define UART_IFLS_1_2  2   /* FIFO 1/2 
> > > > > > full */
> > > > > > +#define UART_IFLS_3_4  3   /* FIFO 3/4 
> > > > > > full */
> > > > > > +#define UART_IFLS_7_8  4   /* FIFO 7/8 
> > > > > > full */
> > > > > >  #define UART_IMSC  0x38/* Interrupt mask 
> > > > > > set/clear register */
> > > > > >  #define UART_IMSC_RIMIM(1 << 0)
> > > > > >  #define UART_IMSC_CTSMIM   (1 << 1)
> > > > > > @@ -115,6 +122,11 @@
> > > > > >  #define UART_MIS   0x40/* Masked interrupt 
> > > > > > status register */
> > > > > >  #define UART_ICR   0x44/* Interrupt clear 
> > > > > > register */
> > > > > >  #define UART_DMACR 0x48/* DMA control register 
> > > > > > */
> > > > > > +#define UART_PID0  0xfe0   /* Peripheral 
> > > > > > identification register 0 */
> > > > > > +#define UART_PID1  0xfe4   /* Peripheral 
> > > > > > identification register 1 */
> > > > > > +#define UART_PID2  0xfe8   /* Peripheral 
> > > > > > identification register 2 */
> > > > > > +#define UART_PID2_REV(x)   ((x) >> 4)
> > > > > 
> > > > > The revision field covers bits 7:4. Should other bits be masked out?
> > > > > PL011 r1p5 documentation says that bits 15:8 must read as zeroes, but
> > > > > that does not necessarily tell what possible future revisions will do.
> > > > 
> > > > I trusted the bits of the documentation you referred to but lets play it
> > > > safe.
> > > > 
> > > > > 
> > > > > > +#define UART_PID3  0xfec   /* Peripheral 
> > > > > > identification register 3 */
> > > > > >  #define UART_SPACE 0x100
> > > > > >  
> > > > > >  void pluartcnprobe(struct consdev *cp);
> > > > > > @@ -150,7 +162,12 @@ struct cdevsw pluartdev =
> > > > > >  void
> > > > > >  pluart_attach_common(struct pluart_softc *sc, int console)
> > > > > >  {
> > > > > &

Re: pluart(4): fifo support

2022-02-27 Thread Anton Lindqvist
On Sun, Feb 27, 2022 at 11:08:14AM +0100, Mark Kettenis wrote:
> > Date: Sun, 27 Feb 2022 09:56:38 +0100
> > From: Anton Lindqvist 
> > 
> > On Sun, Feb 27, 2022 at 06:19:02AM +, Visa Hankala wrote:
> > > On Sat, Feb 26, 2022 at 08:40:25AM +0100, Anton Lindqvist wrote:
> > > > Hi,
> > > > This enables fifo support in pluart(4). While here, I changed the
> > > > attachment output to look more like com(4). Tested on my rpi3b which has
> > > > a 16 byte fifo.
> > > > 
> > > > Comments? OK?
> > > > 
> > > > diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
> > > > index eaa11b6c44b..601435c0e0c 100644
> > > > --- sys/dev/ic/pluart.c
> > > > +++ sys/dev/ic/pluart.c
> > > > @@ -99,6 +99,13 @@
> > > >  #define UART_CR_CTSE   (1 << 14)   /* CTS hardware flow 
> > > > control enable */
> > > >  #define UART_CR_RTSE   (1 << 15)   /* RTS hardware flow 
> > > > control enable */
> > > >  #define UART_IFLS  0x34/* Interrupt FIFO level 
> > > > select register */
> > > > +#define UART_IFLS_RX_SHIFT 3   /* RX level in bits 
> > > > [5:3] */
> > > > +#define UART_IFLS_TX_SHIFT 0   /* TX level in bits 
> > > > [2:0] */
> > > > +#define UART_IFLS_1_8  0   /* FIFO 1/8 full */
> > > > +#define UART_IFLS_1_4  1   /* FIFO 1/4 full */
> > > > +#define UART_IFLS_1_2  2   /* FIFO 1/2 full */
> > > > +#define UART_IFLS_3_4  3   /* FIFO 3/4 full */
> > > > +#define UART_IFLS_7_8  4   /* FIFO 7/8 full */
> > > >  #define UART_IMSC  0x38/* Interrupt mask 
> > > > set/clear register */
> > > >  #define UART_IMSC_RIMIM(1 << 0)
> > > >  #define UART_IMSC_CTSMIM   (1 << 1)
> > > > @@ -115,6 +122,11 @@
> > > >  #define UART_MIS   0x40/* Masked interrupt 
> > > > status register */
> > > >  #define UART_ICR   0x44/* Interrupt clear 
> > > > register */
> > > >  #define UART_DMACR 0x48/* DMA control register 
> > > > */
> > > > +#define UART_PID0  0xfe0   /* Peripheral 
> > > > identification register 0 */
> > > > +#define UART_PID1  0xfe4   /* Peripheral 
> > > > identification register 1 */
> > > > +#define UART_PID2  0xfe8   /* Peripheral 
> > > > identification register 2 */
> > > > +#define UART_PID2_REV(x)   ((x) >> 4)
> > > 
> > > The revision field covers bits 7:4. Should other bits be masked out?
> > > PL011 r1p5 documentation says that bits 15:8 must read as zeroes, but
> > > that does not necessarily tell what possible future revisions will do.
> > 
> > I trusted the bits of the documentation you referred to but lets play it
> > safe.
> > 
> > > 
> > > > +#define UART_PID3  0xfec   /* Peripheral 
> > > > identification register 3 */
> > > >  #define UART_SPACE 0x100
> > > >  
> > > >  void pluartcnprobe(struct consdev *cp);
> > > > @@ -150,7 +162,12 @@ struct cdevsw pluartdev =
> > > >  void
> > > >  pluart_attach_common(struct pluart_softc *sc, int console)
> > > >  {
> > > > -   int maj;
> > > > +   int maj, rev;
> > > > +
> > > > +   rev = UART_PID2_REV(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
> > > > +   UART_PID2));
> > > > +
> > > > +   printf(": rev %d, %d byte fifo\n", rev, rev < 3 ? 16 : 32);
> > > 
> > > Should there be constants for the FIFO sizes?
> > 
> > Sure, fixed.
> > 
> > > 
> > > >  
> > > > if (console) {
> > > > /* Locate the major number. */
> > > > @@ -159,7 +176,7 @@ pluart_attach_common(struct pluart_softc *sc, int 
> > > > console)
> > > > break;
> > > > cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
> > > >  
> > > > -   printf(": console");
> > > > +  

Re: pluart(4): fifo support

2022-02-27 Thread Anton Lindqvist
On Sun, Feb 27, 2022 at 10:46:00AM +, Visa Hankala wrote:
> On Sun, Feb 27, 2022 at 09:56:38AM +0100, Anton Lindqvist wrote:
> > On Sun, Feb 27, 2022 at 06:19:02AM +, Visa Hankala wrote:
> > > On Sat, Feb 26, 2022 at 08:40:25AM +0100, Anton Lindqvist wrote:
> > > > Hi,
> > > > This enables fifo support in pluart(4). While here, I changed the
> > > > attachment output to look more like com(4). Tested on my rpi3b which has
> > > > a 16 byte fifo.
> > > > 
> > > > Comments? OK?
> > > > 
> > > > diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
> > > > index eaa11b6c44b..601435c0e0c 100644
> > > > --- sys/dev/ic/pluart.c
> > > > +++ sys/dev/ic/pluart.c
> > > > @@ -99,6 +99,13 @@
> > > >  #define UART_CR_CTSE   (1 << 14)   /* CTS hardware flow 
> > > > control enable */
> > > >  #define UART_CR_RTSE   (1 << 15)   /* RTS hardware flow 
> > > > control enable */
> > > >  #define UART_IFLS  0x34/* Interrupt FIFO level 
> > > > select register */
> > > > +#define UART_IFLS_RX_SHIFT 3   /* RX level in bits 
> > > > [5:3] */
> > > > +#define UART_IFLS_TX_SHIFT 0   /* TX level in bits 
> > > > [2:0] */
> > > > +#define UART_IFLS_1_8  0   /* FIFO 1/8 full */
> > > > +#define UART_IFLS_1_4  1   /* FIFO 1/4 full */
> > > > +#define UART_IFLS_1_2  2   /* FIFO 1/2 full */
> > > > +#define UART_IFLS_3_4  3   /* FIFO 3/4 full */
> > > > +#define UART_IFLS_7_8  4   /* FIFO 7/8 full */
> > > >  #define UART_IMSC  0x38/* Interrupt mask 
> > > > set/clear register */
> > > >  #define UART_IMSC_RIMIM(1 << 0)
> > > >  #define UART_IMSC_CTSMIM   (1 << 1)
> > > > @@ -115,6 +122,11 @@
> > > >  #define UART_MIS   0x40/* Masked interrupt 
> > > > status register */
> > > >  #define UART_ICR   0x44/* Interrupt clear 
> > > > register */
> > > >  #define UART_DMACR 0x48/* DMA control register 
> > > > */
> > > > +#define UART_PID0  0xfe0   /* Peripheral 
> > > > identification register 0 */
> > > > +#define UART_PID1  0xfe4   /* Peripheral 
> > > > identification register 1 */
> > > > +#define UART_PID2  0xfe8   /* Peripheral 
> > > > identification register 2 */
> > > > +#define UART_PID2_REV(x)   ((x) >> 4)
> > > 
> > > The revision field covers bits 7:4. Should other bits be masked out?
> > > PL011 r1p5 documentation says that bits 15:8 must read as zeroes, but
> > > that does not necessarily tell what possible future revisions will do.
> > 
> > I trusted the bits of the documentation you referred to but lets play it
> > safe.
> 
> I think the documentation is strict about the (currently) reserved bits
> so that any future revisions have the option to use them more easily.
> Hence applying the mask on the revision field is mandatory.
> 
> > > 
> > > > +#define UART_PID3  0xfec   /* Peripheral 
> > > > identification register 3 */
> > > >  #define UART_SPACE 0x100
> > > >  
> > > >  void pluartcnprobe(struct consdev *cp);
> > > > @@ -150,7 +162,12 @@ struct cdevsw pluartdev =
> > > >  void
> > > >  pluart_attach_common(struct pluart_softc *sc, int console)
> > > >  {
> > > > -   int maj;
> > > > +   int maj, rev;
> > > > +
> > > > +   rev = UART_PID2_REV(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
> > > > +   UART_PID2));
> > > > +
> > > > +   printf(": rev %d, %d byte fifo\n", rev, rev < 3 ? 16 : 32);
> > > 
> > > Should there be constants for the FIFO sizes?
> > 
> > Sure, fixed.
> > 
> > > 
> > > >  
> > > > if (console) {
> > > > /* Locate the major number. */
> > > > @@ -159,7 +176,7 @@ pluart_attach_common(struct pluart_softc *sc, int 
> > > > console)
> > > > brea

Re: pluart(4): fifo support

2022-02-27 Thread Anton Lindqvist
On Sun, Feb 27, 2022 at 06:19:02AM +, Visa Hankala wrote:
> On Sat, Feb 26, 2022 at 08:40:25AM +0100, Anton Lindqvist wrote:
> > Hi,
> > This enables fifo support in pluart(4). While here, I changed the
> > attachment output to look more like com(4). Tested on my rpi3b which has
> > a 16 byte fifo.
> > 
> > Comments? OK?
> > 
> > diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
> > index eaa11b6c44b..601435c0e0c 100644
> > --- sys/dev/ic/pluart.c
> > +++ sys/dev/ic/pluart.c
> > @@ -99,6 +99,13 @@
> >  #define UART_CR_CTSE   (1 << 14)   /* CTS hardware flow 
> > control enable */
> >  #define UART_CR_RTSE   (1 << 15)   /* RTS hardware flow 
> > control enable */
> >  #define UART_IFLS  0x34/* Interrupt FIFO level select 
> > register */
> > +#define UART_IFLS_RX_SHIFT 3   /* RX level in bits [5:3] */
> > +#define UART_IFLS_TX_SHIFT 0   /* TX level in bits [2:0] */
> > +#define UART_IFLS_1_8  0   /* FIFO 1/8 full */
> > +#define UART_IFLS_1_4  1   /* FIFO 1/4 full */
> > +#define UART_IFLS_1_2  2   /* FIFO 1/2 full */
> > +#define UART_IFLS_3_4  3   /* FIFO 3/4 full */
> > +#define UART_IFLS_7_8  4   /* FIFO 7/8 full */
> >  #define UART_IMSC  0x38/* Interrupt mask set/clear 
> > register */
> >  #define UART_IMSC_RIMIM(1 << 0)
> >  #define UART_IMSC_CTSMIM   (1 << 1)
> > @@ -115,6 +122,11 @@
> >  #define UART_MIS   0x40/* Masked interrupt status 
> > register */
> >  #define UART_ICR   0x44/* Interrupt clear register */
> >  #define UART_DMACR 0x48/* DMA control register */
> > +#define UART_PID0  0xfe0   /* Peripheral identification 
> > register 0 */
> > +#define UART_PID1  0xfe4   /* Peripheral identification 
> > register 1 */
> > +#define UART_PID2  0xfe8   /* Peripheral identification 
> > register 2 */
> > +#define UART_PID2_REV(x)   ((x) >> 4)
> 
> The revision field covers bits 7:4. Should other bits be masked out?
> PL011 r1p5 documentation says that bits 15:8 must read as zeroes, but
> that does not necessarily tell what possible future revisions will do.

I trusted the bits of the documentation you referred to but lets play it
safe.

> 
> > +#define UART_PID3  0xfec   /* Peripheral identification 
> > register 3 */
> >  #define UART_SPACE 0x100
> >  
> >  void pluartcnprobe(struct consdev *cp);
> > @@ -150,7 +162,12 @@ struct cdevsw pluartdev =
> >  void
> >  pluart_attach_common(struct pluart_softc *sc, int console)
> >  {
> > -   int maj;
> > +   int maj, rev;
> > +
> > +   rev = UART_PID2_REV(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
> > +   UART_PID2));
> > +
> > +   printf(": rev %d, %d byte fifo\n", rev, rev < 3 ? 16 : 32);
> 
> Should there be constants for the FIFO sizes?

Sure, fixed.

> 
> >  
> > if (console) {
> > /* Locate the major number. */
> > @@ -159,7 +176,7 @@ pluart_attach_common(struct pluart_softc *sc, int 
> > console)
> > break;
> > cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
> >  
> > -   printf(": console");
> > +   printf("%s: console\n", sc->sc_dev.dv_xname);
> > SET(sc->sc_hwflags, COM_HW_CONSOLE);
> > }
> >  
> > @@ -171,13 +188,26 @@ pluart_attach_common(struct pluart_softc *sc, int 
> > console)
> > panic("%s: can't establish soft interrupt.",
> > sc->sc_dev.dv_xname);
> >  
> > -   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, (UART_IMSC_RXIM | 
> > UART_IMSC_TXIM));
> > +   /*
> > +* The transmit FIFO size is set to 3/4 of the actual size as interrupts
> > +* can only be triggered when the FIFO is partially full. Once
> > +* triggered, we know that at least this amount is available in the
> > +* FIFO.
> > +*/
> > +   if (rev < 3)
> > +   sc->sc_fifolen = 24;
> > +   else
> > +   sc->sc_fifolen = 12;
> 
> Have the assignments above been swapped by accident?

Nice catch. That's indeed some last minute sloppy refactoring.

> 
> I think the comment could be clearer and more concise

pluart(4): fifo support

2022-02-25 Thread Anton Lindqvist
Hi,
This enables fifo support in pluart(4). While here, I changed the
attachment output to look more like com(4). Tested on my rpi3b which has
a 16 byte fifo.

Comments? OK?

diff --git sys/dev/ic/pluart.c sys/dev/ic/pluart.c
index eaa11b6c44b..601435c0e0c 100644
--- sys/dev/ic/pluart.c
+++ sys/dev/ic/pluart.c
@@ -99,6 +99,13 @@
 #define UART_CR_CTSE   (1 << 14)   /* CTS hardware flow control 
enable */
 #define UART_CR_RTSE   (1 << 15)   /* RTS hardware flow control 
enable */
 #define UART_IFLS  0x34/* Interrupt FIFO level select 
register */
+#define UART_IFLS_RX_SHIFT 3   /* RX level in bits [5:3] */
+#define UART_IFLS_TX_SHIFT 0   /* TX level in bits [2:0] */
+#define UART_IFLS_1_8  0   /* FIFO 1/8 full */
+#define UART_IFLS_1_4  1   /* FIFO 1/4 full */
+#define UART_IFLS_1_2  2   /* FIFO 1/2 full */
+#define UART_IFLS_3_4  3   /* FIFO 3/4 full */
+#define UART_IFLS_7_8  4   /* FIFO 7/8 full */
 #define UART_IMSC  0x38/* Interrupt mask set/clear 
register */
 #define UART_IMSC_RIMIM(1 << 0)
 #define UART_IMSC_CTSMIM   (1 << 1)
@@ -115,6 +122,11 @@
 #define UART_MIS   0x40/* Masked interrupt status 
register */
 #define UART_ICR   0x44/* Interrupt clear register */
 #define UART_DMACR 0x48/* DMA control register */
+#define UART_PID0  0xfe0   /* Peripheral identification 
register 0 */
+#define UART_PID1  0xfe4   /* Peripheral identification 
register 1 */
+#define UART_PID2  0xfe8   /* Peripheral identification 
register 2 */
+#define UART_PID2_REV(x)   ((x) >> 4)
+#define UART_PID3  0xfec   /* Peripheral identification 
register 3 */
 #define UART_SPACE 0x100
 
 void pluartcnprobe(struct consdev *cp);
@@ -150,7 +162,12 @@ struct cdevsw pluartdev =
 void
 pluart_attach_common(struct pluart_softc *sc, int console)
 {
-   int maj;
+   int maj, rev;
+
+   rev = UART_PID2_REV(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+   UART_PID2));
+
+   printf(": rev %d, %d byte fifo\n", rev, rev < 3 ? 16 : 32);
 
if (console) {
/* Locate the major number. */
@@ -159,7 +176,7 @@ pluart_attach_common(struct pluart_softc *sc, int console)
break;
cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
 
-   printf(": console");
+   printf("%s: console\n", sc->sc_dev.dv_xname);
SET(sc->sc_hwflags, COM_HW_CONSOLE);
}
 
@@ -171,13 +188,26 @@ pluart_attach_common(struct pluart_softc *sc, int console)
panic("%s: can't establish soft interrupt.",
sc->sc_dev.dv_xname);
 
-   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, (UART_IMSC_RXIM | 
UART_IMSC_TXIM));
+   /*
+* The transmit FIFO size is set to 3/4 of the actual size as interrupts
+* can only be triggered when the FIFO is partially full. Once
+* triggered, we know that at least this amount is available in the
+* FIFO.
+*/
+   if (rev < 3)
+   sc->sc_fifolen = 24;
+   else
+   sc->sc_fifolen = 12;
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IFLS,
+   (UART_IFLS_3_4 << UART_IFLS_RX_SHIFT) |
+   (UART_IFLS_1_4 << UART_IFLS_TX_SHIFT));
+   sc->sc_imsc = UART_IMSC_RXIM | UART_IMSC_RTIM | UART_IMSC_TXIM;
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, sc->sc_imsc);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_ICR, 0x7ff);
+   /* Enable FIFO. */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H,
-   bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H) &
-   ~UART_LCR_H_FEN);
-
-   printf("\n");
+   bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H) |
+   UART_LCR_H_FEN);
 }
 
 int
@@ -197,19 +227,26 @@ pluart_intr(void *arg)
if (sc->sc_tty == NULL)
return 0;
 
-   if (!ISSET(is, UART_IMSC_RXIM) && !ISSET(is, UART_IMSC_TXIM))
+   if (!ISSET(is, UART_IMSC_RXIM) && !ISSET(is, UART_IMSC_RTIM) &&
+   !ISSET(is, UART_IMSC_TXIM))
return 0;
 
-   if (ISSET(is, UART_IMSC_TXIM) && ISSET(tp->t_state, TS_BUSY)) {
-   CLR(tp->t_state, TS_BUSY | TS_FLUSH);
-   if (sc->sc_halt > 0)
-   wakeup(>t_outq);
-   (*linesw[tp->t_line].l_start)(tp);
+   if (ISSET(is, UART_IMSC_TXIM)) {
+   /* Disable transmit interrupt. */
+   bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC,
+   sc->sc_imsc & ~UART_IMSC_TXIM);
+
+   if (ISSET(tp->t_state, TS_BUSY)) {
+   

Re: wskbd_set_mixervolume

2022-02-10 Thread Anton Lindqvist
On Wed, Feb 09, 2022 at 09:13:58AM +0100, Alexandre Ratchov wrote:
> On Tue, Feb 08, 2022 at 06:59:39PM +0100, Anton Lindqvist wrote:
> > On Tue, Feb 08, 2022 at 07:32:38AM +0100, Alexandre Ratchov wrote:
> > > On Mon, Feb 07, 2022 at 06:55:21PM +0100, Anton Lindqvist wrote:
> > > > On Mon, Feb 07, 2022 at 11:21:43AM +0100, Alexandre Ratchov wrote:
> > > > > On Sun, Feb 06, 2022 at 08:40:35AM +0100, Anton Lindqvist wrote:
> > > > > > 
> > > > > > Polished diff. I'm omitting a necessary refactoring commit making
> > > > > > audio_attach_mi() accept a new cookie argument.
> > > > > > 
> > > > > 
> > > > > I'm not sure to understand the need for the wskbd_audio structure.
> > > > > Couldn't we just store the cookie in audio and wskbd softc structures,
> > > > > then pass it in the wskbd_set_mixervolume_sc() calls ?
> > > > 
> > > > Due to the device caching the data must be stored in either the audio or
> > > > wskbd softc and I don't want to expose the softc structures so I ended
> > > > up introducing wskbd_audio. Dropping the caching would probably make it
> > > > possible to only pass down the cookie to wskbd_set_mixervolume_sc() and
> > > > always do the audio device lookup.
> > > > 
> > > > Is anyone in favor of this approach? I achieves the expected behavior in
> > > > my opinion.
> > > 
> > > IMHO, handling the volume keys this way won't work in the general
> > > case. But for the short term we've no other options, have we?
> > > 
> > > AFAICS, you're fixing a concrete use-case by tweaking what already
> > > exists, this won't make things more broken than they already are. I'm
> > > OK with it.
> > 
> > Here's the complete diff including adding a cookie argument to
> > audio_attach_mi().
> 
> Is the caching necessary? device_lookup() seems cheap and there are at
> most two devices in most cases. Keeping the code minimal especially on
> rare and non-performace-critical code-paths would be nice.
> 
> If you choose to drop the caching, this would allow to just add a a
> new "cookie" argument to wskbd_set_mixervolume(), similarly to what
> you did for audio_attach_mi()

Sure, I ended up adding a new function after all since the
wskbd_set_mixervolume() prototype is not present in any header at this
point.

diff --git sys/arch/hppa/gsc/harmony.c sys/arch/hppa/gsc/harmony.c
index 033a3d2c356..d5748fac4b1 100644
--- sys/arch/hppa/gsc/harmony.c
+++ sys/arch/hppa/gsc/harmony.c
@@ -249,7 +249,7 @@ harmony_attach(parent, self, aux)
if ((rev & CS4215_REV_VER) >= CS4215_REV_VER_E)
sc->sc_hasulinear8 = 1;
 
-   audio_attach_mi(_sa_hw_if, sc, >sc_dv);
+   audio_attach_mi(_sa_hw_if, sc, NULL, >sc_dv);
 
timeout_set(>sc_acc_tmo, harmony_acc_tmo, sc);
sc->sc_acc_num = 0xa5a5a5a5;
diff --git sys/arch/luna88k/cbus/nec86.c sys/arch/luna88k/cbus/nec86.c
index b6516cc4888..dc4e2069ddd 100644
--- sys/arch/luna88k/cbus/nec86.c
+++ sys/arch/luna88k/cbus/nec86.c
@@ -237,7 +237,7 @@ nec86_attachsubr(struct nec86_softc *sc)
 
if (sc->sc_attached == 0) {
printf(": %s\n", boardname[ysc->model]);
-   audio_attach_mi(_hw_if, ysc, >sc_dev);
+   audio_attach_mi(_hw_if, ysc, NULL, >sc_dev);
sc->sc_attached = 1;
}
 }
diff --git sys/arch/macppc/dev/aoa.c sys/arch/macppc/dev/aoa.c
index a2ca8e10a95..638da4b1669 100644
--- sys/arch/macppc/dev/aoa.c
+++ sys/arch/macppc/dev/aoa.c
@@ -134,7 +134,7 @@ aoa_defer(struct device *dev)
 {
struct aoa_softc *sc = (struct aoa_softc *)dev;
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
deq_reset(sc);
 }
 
diff --git sys/arch/macppc/dev/awacs.c sys/arch/macppc/dev/awacs.c
index 8ea7d4869a0..adcafcf79fb 100644
--- sys/arch/macppc/dev/awacs.c
+++ sys/arch/macppc/dev/awacs.c
@@ -340,7 +340,7 @@ awacs_attach(struct device *parent, struct device *self, 
void *aux)
awacs_halt_input(sc);
printf("\n");
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
 }
 
 u_int
diff --git sys/arch/macppc/dev/daca.c sys/arch/macppc/dev/daca.c
index 070b839c99a..91b078dd254 100644
--- sys/arch/macppc/dev/daca.c
+++ sys/arch/macppc/dev/daca.c
@@ -154,7 +154,7 @@ daca_defer(struct device *dev)
 
/* XXX If i2c has failed to attach, what should we do? */
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
 
daca_init(sc);
 }
diff --git sys/arch/macppc/de

Re: wskbd_set_mixervolume

2022-02-08 Thread Anton Lindqvist
On Tue, Feb 08, 2022 at 07:32:38AM +0100, Alexandre Ratchov wrote:
> On Mon, Feb 07, 2022 at 06:55:21PM +0100, Anton Lindqvist wrote:
> > On Mon, Feb 07, 2022 at 11:21:43AM +0100, Alexandre Ratchov wrote:
> > > On Sun, Feb 06, 2022 at 08:40:35AM +0100, Anton Lindqvist wrote:
> > > > 
> > > > Polished diff. I'm omitting a necessary refactoring commit making
> > > > audio_attach_mi() accept a new cookie argument.
> > > > 
> > > 
> > > I'm not sure to understand the need for the wskbd_audio structure.
> > > Couldn't we just store the cookie in audio and wskbd softc structures,
> > > then pass it in the wskbd_set_mixervolume_sc() calls ?
> > 
> > Due to the device caching the data must be stored in either the audio or
> > wskbd softc and I don't want to expose the softc structures so I ended
> > up introducing wskbd_audio. Dropping the caching would probably make it
> > possible to only pass down the cookie to wskbd_set_mixervolume_sc() and
> > always do the audio device lookup.
> > 
> > Is anyone in favor of this approach? I achieves the expected behavior in
> > my opinion.
> 
> IMHO, handling the volume keys this way won't work in the general
> case. But for the short term we've no other options, have we?
> 
> AFAICS, you're fixing a concrete use-case by tweaking what already
> exists, this won't make things more broken than they already are. I'm
> OK with it.

Here's the complete diff including adding a cookie argument to
audio_attach_mi().
diff --git sys/arch/hppa/gsc/harmony.c sys/arch/hppa/gsc/harmony.c
index 033a3d2c356..d5748fac4b1 100644
--- sys/arch/hppa/gsc/harmony.c
+++ sys/arch/hppa/gsc/harmony.c
@@ -249,7 +249,7 @@ harmony_attach(parent, self, aux)
if ((rev & CS4215_REV_VER) >= CS4215_REV_VER_E)
sc->sc_hasulinear8 = 1;
 
-   audio_attach_mi(_sa_hw_if, sc, >sc_dv);
+   audio_attach_mi(_sa_hw_if, sc, NULL, >sc_dv);
 
timeout_set(>sc_acc_tmo, harmony_acc_tmo, sc);
sc->sc_acc_num = 0xa5a5a5a5;
diff --git sys/arch/luna88k/cbus/nec86.c sys/arch/luna88k/cbus/nec86.c
index b6516cc4888..dc4e2069ddd 100644
--- sys/arch/luna88k/cbus/nec86.c
+++ sys/arch/luna88k/cbus/nec86.c
@@ -237,7 +237,7 @@ nec86_attachsubr(struct nec86_softc *sc)
 
if (sc->sc_attached == 0) {
printf(": %s\n", boardname[ysc->model]);
-   audio_attach_mi(_hw_if, ysc, >sc_dev);
+   audio_attach_mi(_hw_if, ysc, NULL, >sc_dev);
sc->sc_attached = 1;
}
 }
diff --git sys/arch/macppc/dev/aoa.c sys/arch/macppc/dev/aoa.c
index a2ca8e10a95..638da4b1669 100644
--- sys/arch/macppc/dev/aoa.c
+++ sys/arch/macppc/dev/aoa.c
@@ -134,7 +134,7 @@ aoa_defer(struct device *dev)
 {
struct aoa_softc *sc = (struct aoa_softc *)dev;
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
deq_reset(sc);
 }
 
diff --git sys/arch/macppc/dev/awacs.c sys/arch/macppc/dev/awacs.c
index 8ea7d4869a0..adcafcf79fb 100644
--- sys/arch/macppc/dev/awacs.c
+++ sys/arch/macppc/dev/awacs.c
@@ -340,7 +340,7 @@ awacs_attach(struct device *parent, struct device *self, 
void *aux)
awacs_halt_input(sc);
printf("\n");
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
 }
 
 u_int
diff --git sys/arch/macppc/dev/daca.c sys/arch/macppc/dev/daca.c
index 070b839c99a..91b078dd254 100644
--- sys/arch/macppc/dev/daca.c
+++ sys/arch/macppc/dev/daca.c
@@ -154,7 +154,7 @@ daca_defer(struct device *dev)
 
/* XXX If i2c has failed to attach, what should we do? */
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
 
daca_init(sc);
 }
diff --git sys/arch/macppc/dev/onyx.c sys/arch/macppc/dev/onyx.c
index c279258f091..9252d1c7376 100644
--- sys/arch/macppc/dev/onyx.c
+++ sys/arch/macppc/dev/onyx.c
@@ -165,7 +165,7 @@ onyx_defer(struct device *dev)
 
/* XXX If i2c has failed to attach, what should we do? */
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
 
deq_reset(sc);
onyx_set_volume(sc, 192, 192);
diff --git sys/arch/macppc/dev/snapper.c sys/arch/macppc/dev/snapper.c
index 3fbf58aec0f..13784f6d207 100644
--- sys/arch/macppc/dev/snapper.c
+++ sys/arch/macppc/dev/snapper.c
@@ -486,7 +486,7 @@ snapper_defer(struct device *dev)
 
/* XXX If i2c has failed to attach, what should we do? */
 
-   audio_attach_mi(_hw_if, sc, >sc_dev);
+   audio_attach_mi(_hw_if, sc, NULL, >sc_dev);
 
/* kiic_setmode(sc->sc_i2c, I2C_STDSUBMODE); */
snapper_init(sc);
diff --git sys/arch/macppc/dev/tumbler.c sys/arch/macppc/dev/tumbler.c
index 

Re: wskbd_set_mixervolume

2022-02-07 Thread Anton Lindqvist
On Mon, Feb 07, 2022 at 11:43:43AM +0100, Alexandre Ratchov wrote:
> On Sat, Feb 05, 2022 at 06:30:43PM +0100, Claudio Jeker wrote:
> > On Sat, Feb 05, 2022 at 12:28:08PM +0100, Mark Kettenis wrote:
> > > > Date: Sat, 5 Feb 2022 09:29:42 +0100
> > > > From: Anton Lindqvist 
> > > > 
> > > > Hi,
> > > > I recently got a USB headset with physical volume buttons, handled by
> > > > ucc(4). However, after enabling the device in sndiod the volume buttons
> > > > does not cause the volume to change. Turns out wskbd_set_mixervolume()
> > > > is only propagating volume changes to first attached audio device. Is
> > > > their any good not to consider all attached audio devices?
> > > 
> > > I think this is tricky.  The mixer values of different audio devices
> > > may start out differently and may have different granularity and
> > > probably operate on a different scale.  This may lead to situations
> > > where as you turn the volume up and down, the relative output volume
> > > between devices changes considerably.  I also think that your
> > > implementation will unmute all audio devices as soon as you touch the
> > > volume control buttons, which is probably not desirable.
> > > 
> > > Thinking about other ways to do this, we could:
> > > 
> > > - Add a knob that allows the user to control which audio device is
> > >   controlled by the volume control buttons.  The choice could include
> > >   "none" and "all" as well as the individual devices.
> > > 
> > > - Add infrastructure to bind specific keyboards to specific audio
> > >   devices, a bit like how we support binding specific wskbd devices to
> > >   specific wsdisplay devices.
> > > 
> > > The first suggestion is probably relatively easy to achieve.  The
> > > implementation of the latter would defenitely need more thought and
> > > discussion.
> > > 
> > > The "none" choice above would (partly) solve another issue where
> > > userland applications see the key presses and act upon them even
> > > though the kernel already did the volume adjustment.
> > 
> > There is a 3rd option of passing the information to sndiod and let it do
> > the volume scaling.
> >  
> 
> Here's a small WIP program to do so. It also adds a key to cycle
> through audio devices.
> 
> https://github.com/ratchov/sndiokeys
> 
> By default it uses Ctrl+Alt+{plus,minus,0} because multimedia keys are
> already used.
> 
> Anton, I've no headphones with buttons to test, does this work for
> yours?

Interesting! I cannot get to run under X, it fails in XGetKeyboardMapping:

(gdb) r
Starting program: /tmp/sndiokeys/sndiokeys 
X Error of failed request:  BadAccess (attempt to access private resource 
denied)
  Major opcode of failed request:  33 (X_GrabKey)
  Serial number of failed request:  12
  Current serial number in output stream:  76

Breakpoint 1, _libc_exit (status=1) at /home/src2/lib/libc/stdlib/exit.c:54
54  /home/src2/lib/libc/stdlib/exit.c: No such file or directory.
(gdb) bt
#0  _libc_exit (status=1) at /home/src2/lib/libc/stdlib/exit.c:54
#1  0x0cfba76512b1 in _XDefaultError () from /usr/X11R6/lib/libX11.so.17.1
#2  0x0cfba76514a9 in _XError () from /usr/X11R6/lib/libX11.so.17.1
#3  0x0cfba764d47a in handle_response () from /usr/X11R6/lib/libX11.so.17.1
#4  0x0cfba764dd50 in _XReply () from /usr/X11R6/lib/libX11.so.17.1
#5  0x0cfba762d8ba in XGetKeyboardMapping () from 
/usr/X11R6/lib/libX11.so.17.1
#6  0x0cf94a4778f7 in grab_keys () at sndiokeys.c:318
#7  0x0cf94a477279 in main (argc=0, argv=0x7f7dd760) at sndiokeys.c:529



Re: wskbd_set_mixervolume

2022-02-07 Thread Anton Lindqvist
On Mon, Feb 07, 2022 at 11:21:43AM +0100, Alexandre Ratchov wrote:
> On Sun, Feb 06, 2022 at 08:40:35AM +0100, Anton Lindqvist wrote:
> > 
> > Polished diff. I'm omitting a necessary refactoring commit making
> > audio_attach_mi() accept a new cookie argument.
> > 
> 
> I'm not sure to understand the need for the wskbd_audio structure.
> Couldn't we just store the cookie in audio and wskbd softc structures,
> then pass it in the wskbd_set_mixervolume_sc() calls ?

Due to the device caching the data must be stored in either the audio or
wskbd softc and I don't want to expose the softc structures so I ended
up introducing wskbd_audio. Dropping the caching would probably make it
possible to only pass down the cookie to wskbd_set_mixervolume_sc() and
always do the audio device lookup.

Is anyone in favor of this approach? I achieves the expected behavior in
my opinion.



Re: wskbd_set_mixervolume

2022-02-05 Thread Anton Lindqvist
On Sat, Feb 05, 2022 at 02:46:53PM +0100, Anton Lindqvist wrote:
> On Sat, Feb 05, 2022 at 12:28:08PM +0100, Mark Kettenis wrote:
> > > Date: Sat, 5 Feb 2022 09:29:42 +0100
> > > From: Anton Lindqvist 
> > > 
> > > Hi,
> > > I recently got a USB headset with physical volume buttons, handled by
> > > ucc(4). However, after enabling the device in sndiod the volume buttons
> > > does not cause the volume to change. Turns out wskbd_set_mixervolume()
> > > is only propagating volume changes to first attached audio device. Is
> > > their any good not to consider all attached audio devices?
> > 
> > I think this is tricky.  The mixer values of different audio devices
> > may start out differently and may have different granularity and
> > probably operate on a different scale.  This may lead to situations
> > where as you turn the volume up and down, the relative output volume
> > between devices changes considerably.  I also think that your
> > implementation will unmute all audio devices as soon as you touch the
> > volume control buttons, which is probably not desirable.
> > 
> > Thinking about other ways to do this, we could:
> > 
> > - Add a knob that allows the user to control which audio device is
> >   controlled by the volume control buttons.  The choice could include
> >   "none" and "all" as well as the individual devices.
> > 
> > - Add infrastructure to bind specific keyboards to specific audio
> >   devices, a bit like how we support binding specific wskbd devices to
> >   specific wsdisplay devices.
> > 
> > The first suggestion is probably relatively easy to achieve.  The
> > implementation of the latter would defenitely need more thought and
> > discussion.
> > 
> > The "none" choice above would (partly) solve another issue where
> > userland applications see the key presses and act upon them even
> > though the kernel already did the volume adjustment.
> > 
> > Cheers,
> > 
> > Mark
> 
> Thanks for the input. Another approach would be to correlate the audio
> and wskbd device. Here's a proof of concept diff that propagates a
> "cookie" from the common point of attachment, being uhub for my
> particular device. The same cookie is later used to find the matching
> audio device while handling volume keys. The found audio device could
> probably be cached inside `struct wskbd_softc' if it grabs a device
> reference. I'm taking quite a few shortcuts here to avoid changing the
> prototypes of commonly used functions.

Polished diff. I'm omitting a necessary refactoring commit making
audio_attach_mi() accept a new cookie argument.

diff --git sys/dev/audio.c sys/dev/audio.c
index 64696025a50..f2b40637771 100644
--- sys/dev/audio.c
+++ sys/dev/audio.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include/* struct wskbd_audio */
 #include "audio.h"
 #include "wskbd.h"
 
@@ -96,6 +97,8 @@ struct wskbd_vol
 #define WSKBD_MUTE_DISABLE 2
 #define WSKBD_MUTE_ENABLE  3
 };
+
+int wskbd_set_mixervolume_unit(int, long, long);
 #endif
 
 /*
@@ -2455,10 +2458,6 @@ wskbd_mixer_init(struct audio_softc *sc)
};
int i;
 
-   if (sc->dev.dv_unit != 0) {
-   DPRINTF("%s: not configuring wskbd keys\n", DEVNAME(sc));
-   return;
-   }
for (i = 0; i < sizeof(spkr_names) / sizeof(spkr_names[0]); i++) {
if (wskbd_initvol(sc, >spkr,
spkr_names[i].cn, spkr_names[i].dn))
@@ -2569,13 +2568,55 @@ wskbd_set_mixermute(long mute, long out)
return 0;
 }
 
+int
+wskbd_set_mixervolume_sc(struct wskbd_audio *audio, long dir, long out)
+{
+   if (audio->dev != NULL) {
+   if ((audio->dev->dv_flags & DVF_ACTIVE) == 0) {
+   /* Audio device gone, fallback to audio0. */
+   device_unref(audio->dev);
+   audio->dev = NULL;
+   audio->unit = 0;
+   }
+   } else if (audio->cookie != NULL) {
+   void *cookie;
+   int i;
+
+   cookie = audio->cookie;
+   audio->cookie = NULL;
+   for (i = 0; i < audio_cd.cd_ndevs; i++) {
+   struct audio_softc *sc;
+
+   sc = (struct audio_softc *)device_lookup(_cd, i);
+   if (sc == NULL)
+   continue;
+   if (sc->cookie != cookie) {
+   device_unref(>dev);
+   continue;
+   }
+
+   audio->dev = (struct device 

Re: wskbd_set_mixervolume

2022-02-05 Thread Anton Lindqvist
On Sat, Feb 05, 2022 at 12:28:08PM +0100, Mark Kettenis wrote:
> > Date: Sat, 5 Feb 2022 09:29:42 +0100
> > From: Anton Lindqvist 
> > 
> > Hi,
> > I recently got a USB headset with physical volume buttons, handled by
> > ucc(4). However, after enabling the device in sndiod the volume buttons
> > does not cause the volume to change. Turns out wskbd_set_mixervolume()
> > is only propagating volume changes to first attached audio device. Is
> > their any good not to consider all attached audio devices?
> 
> I think this is tricky.  The mixer values of different audio devices
> may start out differently and may have different granularity and
> probably operate on a different scale.  This may lead to situations
> where as you turn the volume up and down, the relative output volume
> between devices changes considerably.  I also think that your
> implementation will unmute all audio devices as soon as you touch the
> volume control buttons, which is probably not desirable.
> 
> Thinking about other ways to do this, we could:
> 
> - Add a knob that allows the user to control which audio device is
>   controlled by the volume control buttons.  The choice could include
>   "none" and "all" as well as the individual devices.
> 
> - Add infrastructure to bind specific keyboards to specific audio
>   devices, a bit like how we support binding specific wskbd devices to
>   specific wsdisplay devices.
> 
> The first suggestion is probably relatively easy to achieve.  The
> implementation of the latter would defenitely need more thought and
> discussion.
> 
> The "none" choice above would (partly) solve another issue where
> userland applications see the key presses and act upon them even
> though the kernel already did the volume adjustment.
> 
> Cheers,
> 
> Mark

Thanks for the input. Another approach would be to correlate the audio
and wskbd device. Here's a proof of concept diff that propagates a
"cookie" from the common point of attachment, being uhub for my
particular device. The same cookie is later used to find the matching
audio device while handling volume keys. The found audio device could
probably be cached inside `struct wskbd_softc' if it grabs a device
reference. I'm taking quite a few shortcuts here to avoid changing the
prototypes of commonly used functions.

diff --git sys/dev/audio.c sys/dev/audio.c
index ec52ee6ef01..f412e497edd 100644
--- sys/dev/audio.c
+++ sys/dev/audio.c
@@ -112,6 +112,7 @@ struct mixer_ev {
 struct audio_softc {
struct device dev;
struct audio_hw_if *ops;/* driver funcs */
+   void *cookie;   /* XXX */
void *arg;  /* first arg to driver funcs */
int mode;   /* bitmask of AUMODE_* */
int quiesce;/* device suspended */
@@ -1236,6 +1237,7 @@ audio_attach(struct device *parent, struct device *self, 
void *aux)
}
 #endif
sc->ops = ops;
+   sc->cookie = sa->cookie;
sc->arg = arg;
 
 #if NWSKBD > 0
@@ -1474,6 +1476,24 @@ audio_attach_mi(struct audio_hw_if *ops, void *arg, 
struct device *dev)
aa.type = AUDIODEV_TYPE_AUDIO;
aa.hwif = ops;
aa.hdl = arg;
+   aa.cookie = NULL;
+
+   /*
+* attach this driver to the caller (hardware driver), this
+* checks the kernel config and possibly calls audio_attach()
+*/
+   return config_found_sm(dev, , audioprint, audio_submatch);
+}
+
+struct device *
+audio_attach_mi1(struct audio_hw_if *ops, void *arg, struct device *dev, void 
*cookie)
+{
+   struct audio_attach_args aa;
+
+   aa.type = AUDIODEV_TYPE_AUDIO;
+   aa.hwif = ops;
+   aa.hdl = arg;
+   aa.cookie = cookie;
 
/*
 * attach this driver to the caller (hardware driver), this
@@ -2452,10 +2472,6 @@ wskbd_mixer_init(struct audio_softc *sc)
};
int i;
 
-   if (sc->dev.dv_unit != 0) {
-   DPRINTF("%s: not configuring wskbd keys\n", DEVNAME(sc));
-   return;
-   }
for (i = 0; i < sizeof(spkr_names) / sizeof(spkr_names[0]); i++) {
if (wskbd_initvol(sc, >spkr,
spkr_names[i].cn, spkr_names[i].dn))
@@ -2566,6 +2582,37 @@ wskbd_set_mixermute(long mute, long out)
return 0;
 }
 
+int
+wskbd_set_mixervolume1(void *cookie, long dir, long out)
+{
+   int minor;
+
+   for (minor = 0; minor < audio_cd.cd_ndevs; minor++) {
+   struct audio_softc *sc;
+   struct wskbd_vol *vol;
+
+   sc = (struct audio_softc *)device_lookup(_cd, minor);
+   if (sc == NULL)
+   continue;
+   if (sc->cookie != cookie) {
+   device

wskbd_set_mixervolume

2022-02-05 Thread Anton Lindqvist
Hi,
I recently got a USB headset with physical volume buttons, handled by
ucc(4). However, after enabling the device in sndiod the volume buttons
does not cause the volume to change. Turns out wskbd_set_mixervolume()
is only propagating volume changes to first attached audio device. Is
their any good not to consider all attached audio devices?

The diff below gives me the desired behavior by propagating volume
changes to all attached audio devices.

diff --git sys/dev/audio.c sys/dev/audio.c
index ec52ee6ef01..ca19557d39e 100644
--- sys/dev/audio.c
+++ sys/dev/audio.c
@@ -2452,10 +2452,6 @@ wskbd_mixer_init(struct audio_softc *sc)
};
int i;
 
-   if (sc->dev.dv_unit != 0) {
-   DPRINTF("%s: not configuring wskbd keys\n", DEVNAME(sc));
-   return;
-   }
for (i = 0; i < sizeof(spkr_names) / sizeof(spkr_names[0]); i++) {
if (wskbd_initvol(sc, >spkr,
spkr_names[i].cn, spkr_names[i].dn))
@@ -2569,19 +2565,26 @@ wskbd_set_mixermute(long mute, long out)
 int
 wskbd_set_mixervolume(long dir, long out)
 {
-   struct audio_softc *sc;
-   struct wskbd_vol *vol;
+   int error = ENODEV;
+   int minor;
 
-   sc = (struct audio_softc *)device_lookup(_cd, 0);
-   if (sc == NULL)
-   return ENODEV;
-   vol = out ? >spkr : >mic;
-   if (dir == 0)
-   vol->mute_pending ^= WSKBD_MUTE_TOGGLE;
-   else
-   vol->val_pending += dir;
-   if (!task_add(systq, >wskbd_task))
-   device_unref(>dev);
-   return 0;
+   for (minor = 0; minor < audio_cd.cd_ndevs; minor++) {
+   struct audio_softc *sc;
+   struct wskbd_vol *vol;
+
+   sc = (struct audio_softc *)device_lookup(_cd, minor);
+   if (sc == NULL)
+   continue;
+   vol = out ? >spkr : >mic;
+   if (dir == 0)
+   vol->mute_pending ^= WSKBD_MUTE_TOGGLE;
+   else
+   vol->val_pending += dir;
+   if (!task_add(systq, >wskbd_task))
+   device_unref(>dev);
+   error = 0;
+   }
+
+   return error;
 }
 #endif /* NWSKBD > 0 */



Re: Properly check if ACPI devices are enabled

2022-01-24 Thread Anton Lindqvist
On Mon, Jan 24, 2022 at 08:40:36PM +0100, Mark Kettenis wrote:
> > Date: Mon, 24 Jan 2022 20:19:46 +0100
> > From: Anton Lindqvist 
> > 
> > On Mon, Jan 24, 2022 at 05:31:49PM +0100, Mark Kettenis wrote:
> > > Currently we attach ACPI devices that are present in a machine.
> > > However, in some cases ACPI devices can be present, but not enabled.
> > > Attaching a device driver to devices that are not enabled is not a
> > > good idea since reading and writing from/to its registers will fail
> > > and the driver will malfunction in interesting ways.  Such as a com(4)
> > > serial port that is misdetected and hangs the kernel when it is
> > > actually opened.
> > > 
> > > The diff below makes sure we only enable devices that are actually
> > > enabled.  This may cause some devices to disappear in OpenBSD.
> > > However those devices should have been unusable anyway, so that isn't
> > > an issue.
> > > 
> > > ok?
> > 
> > According to the ACPI specification[1]:
> > 
> > > A device can only decode its hardware resources if both bits 0 and 1 are
> > > set. If the device is not present (bit [0] cleared) or not enabled (bit
> > > [1] cleared), then the device must not decode its resources.
> 
> Just before that it says:
> 
>   If bit [0] is cleared, then bit 1 must also be cleared (in other
>   words, a device that is not present cannot be enabled).
> 
> > Should we therefore check for presence of both STA_PRESENT and
> > STA_ENABLED?
> 
> So according to the ACPI specification we don't need to do that.
> Should we do it just to be safe?

I would still vote for it.



Re: Properly check if ACPI devices are enabled

2022-01-24 Thread Anton Lindqvist
On Mon, Jan 24, 2022 at 05:31:49PM +0100, Mark Kettenis wrote:
> Currently we attach ACPI devices that are present in a machine.
> However, in some cases ACPI devices can be present, but not enabled.
> Attaching a device driver to devices that are not enabled is not a
> good idea since reading and writing from/to its registers will fail
> and the driver will malfunction in interesting ways.  Such as a com(4)
> serial port that is misdetected and hangs the kernel when it is
> actually opened.
> 
> The diff below makes sure we only enable devices that are actually
> enabled.  This may cause some devices to disappear in OpenBSD.
> However those devices should have been unusable anyway, so that isn't
> an issue.
> 
> ok?

According to the ACPI specification[1]:

> A device can only decode its hardware resources if both bits 0 and 1 are
> set. If the device is not present (bit [0] cleared) or not enabled (bit
> [1] cleared), then the device must not decode its resources.

Should we therefore check for presence of both STA_PRESENT and
STA_ENABLED?

[1] 
https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/06_Device_Configuration/Device_Configuration.html#device-insertion-removal-and-status-objects



Re: uhidppctl(8)

2021-12-22 Thread Anton Lindqvist
On Tue, Dec 21, 2021 at 03:49:47PM -0500, jwinnie@tilde.institute wrote:
> Hello OpenBSD developers,
> 
> I am interested in contributing to improve the uhidpp(4)
> (Logitech Unifying Reciever) support in OpenBSD.
> 
> Currently, the uhidpp(4) driver only handles detecting certain
> sensors, but I would like more robust support for these devices,
> including:
> 
> * pairing and unpairing devices on the command-line
> * controlling the scrolling speed/auxiliary buttons of wireless mice
> 
> Do you know where I should start? Should I work on the uhidpp(4)
> driver, or should I go ahead and start writing a command-line utility,
> like uhidppctl(8)?

There's already Solaar[1], I have used it on Linux to pair devices but I
doubt it works on OpenBSD. It would probably need a new /dev/uhidppX
character device similar to /dev/fido/X in order to communicate with the
receiver from user space through uhid(4). The device pairing protocol is
documented here[2].

[1] https://github.com/pwr-Solaar/Solaar
[2] 
https://lekensteyn.nl/files/logitech/logitech_hidpp10_specification_for_Unifying_Receivers.pdf



Re: com(4) at acpi(4) on amd64

2021-12-09 Thread Anton Lindqvist
On Tue, Dec 07, 2021 at 01:08:45PM +0100, Mark Kettenis wrote:
> > Date: Tue, 7 Dec 2021 11:30:48 +0100
> > From: Anton Lindqvist 
> > 
> > On Mon, Dec 06, 2021 at 10:25:34PM +0100, Mark Kettenis wrote:
> > > > Date: Mon, 6 Dec 2021 21:45:03 +0100
> > > > From: Anton Lindqvist 
> > > > 
> > > > On Mon, Dec 06, 2021 at 09:23:45PM +0100, Mark Kettenis wrote:
> > > > > > Date: Mon, 6 Dec 2021 21:08:04 +0100
> > > > > > From: Patrick Wildt 
> > > > > > 
> > > > > > Hi,
> > > > > > 
> > > > > > On one machine I had the pleasure of having to try and use the
> > > > > > Serial-over-LAN feature which shows up as just another com(4)
> > > > > > device.  Instead of having to manually add a com(4) at isa(4)
> > > > > > I figured it would be nicer to have them attach via ACPI.  At
> > > > > > least on that machine, the SOL definitely shows up in the DSDT.
> > > > > > 
> > > > > > Since I don't want to break any legacy machines, I figured I'd
> > > > > > keep ignoring the isa(4) addresses specified in amd64's GENERIC.
> > > > > > 
> > > > > > Right now this diff is more about putting it out there, not about
> > > > > > asking for OKs, as amd64 isn't really my strong suit.  If people
> > > > > > are interested, I can definitely put in all the feedback there is.
> > > > > > 
> > > > > > Patrick
> > > > > 
> > > > > anton@ has a better diff he's working on
> > > > 
> > > > Here's the diff in its current state. There's one thing I haven't had
> > > > the time to figure out yet: in order to get interrupts working on my
> > > > apu2 I had to explicit pass LR_EXTIRQ_MODE (aaa_irq_flags is zero) to
> > > > acpi_intr_establish() which causes IST_EDGE to be passed to
> > > > intr_establish(). Worth noting is that this matches what com at isa
> > > > already does. This was however not necessary on my amd64 build machine
> > > > where aaa_irq_flags also is zero.
> > > 
> > > Actually, it seems we're parsing the ACPI interrupt resource
> > > descriptor wrong.  The decompiled DSDTs I have here seem to use
> > > IRQNoFlags() for the interrupts, which apparently implies the
> > > interrupt is edge-triggered.
> > > 
> > > Let me see if I can cook a diff.
> > 
> > Updated diff now that kettenis@ fixed parsing of the irq flags.
> 
> A few comments below.
> 
> > diff --git share/man/man4/com.4 share/man/man4/com.4
> > index 73b421f2ca7..e54255fe0d6 100644
> > --- share/man/man4/com.4
> > +++ share/man/man4/com.4
> > @@ -61,11 +61,13 @@
> >  .Cd "com0 at isa? port 0x3f8 irq 4"
> >  .Cd "com1 at isa? port 0x2f8 irq 3"
> >  .Pp
> > +.Cd "# arm64 and amd64"
> > +.Cd "com* at acpi?"
> > +.Pp
> >  .Cd "# armv7"
> >  .Cd "com* at fdt?"
> >  .Pp
> >  .Cd "# arm64"
> > -.Cd "com* at acpi?"
> >  .Cd "com* at fdt?"
> 
> The armv7 and arm64 entries can be combined now
> 
> >  .Pp
> >  .Cd "# hppa"
> > diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
> > index ecccd1323d9..87fcaced306 100644
> > --- sys/arch/amd64/conf/GENERIC
> > +++ sys/arch/amd64/conf/GENERIC
> > @@ -65,6 +65,11 @@ amdgpio* at acpi?
> >  aplgpio*   at acpi?
> >  bytgpio*   at acpi?
> >  chvgpio*   at acpi?
> > +com0   at acpi?
> > +com1   at acpi?
> > +com2   at acpi?
> > +com3   at acpi?
> > +com*   at acpi?
> >  glkgpio*   at acpi?
> >  pchgpio*   at acpi?
> >  sdhc*  at acpi?
> > diff --git sys/arch/amd64/conf/RAMDISK sys/arch/amd64/conf/RAMDISK
> > index 6041293b287..a5f10b357dd 100644
> > --- sys/arch/amd64/conf/RAMDISK
> > +++ sys/arch/amd64/conf/RAMDISK
> > @@ -34,6 +34,9 @@ acpipci*  at acpi?
> >  acpiprt*   at acpi?
> >  acpimadt0  at acpi?
> >  #acpitz*   at acpi?
> > +com0   at acpi?
> > +com1   at acpi?
> > +com*   at acpi?
> >  
> >  mpbios0at bios0
> 
> As Theo pointed out, this may not be entirely fool-proof.  We probe
> acpi(4) before isa(4), which is good.  Since we prevent ISA devices
> from attaching to address

Re: com(4) at acpi(4) on amd64

2021-12-07 Thread Anton Lindqvist
On Mon, Dec 06, 2021 at 10:25:34PM +0100, Mark Kettenis wrote:
> > Date: Mon, 6 Dec 2021 21:45:03 +0100
> > From: Anton Lindqvist 
> > 
> > On Mon, Dec 06, 2021 at 09:23:45PM +0100, Mark Kettenis wrote:
> > > > Date: Mon, 6 Dec 2021 21:08:04 +0100
> > > > From: Patrick Wildt 
> > > > 
> > > > Hi,
> > > > 
> > > > On one machine I had the pleasure of having to try and use the
> > > > Serial-over-LAN feature which shows up as just another com(4)
> > > > device.  Instead of having to manually add a com(4) at isa(4)
> > > > I figured it would be nicer to have them attach via ACPI.  At
> > > > least on that machine, the SOL definitely shows up in the DSDT.
> > > > 
> > > > Since I don't want to break any legacy machines, I figured I'd
> > > > keep ignoring the isa(4) addresses specified in amd64's GENERIC.
> > > > 
> > > > Right now this diff is more about putting it out there, not about
> > > > asking for OKs, as amd64 isn't really my strong suit.  If people
> > > > are interested, I can definitely put in all the feedback there is.
> > > > 
> > > > Patrick
> > > 
> > > anton@ has a better diff he's working on
> > 
> > Here's the diff in its current state. There's one thing I haven't had
> > the time to figure out yet: in order to get interrupts working on my
> > apu2 I had to explicit pass LR_EXTIRQ_MODE (aaa_irq_flags is zero) to
> > acpi_intr_establish() which causes IST_EDGE to be passed to
> > intr_establish(). Worth noting is that this matches what com at isa
> > already does. This was however not necessary on my amd64 build machine
> > where aaa_irq_flags also is zero.
> 
> Actually, it seems we're parsing the ACPI interrupt resource
> descriptor wrong.  The decompiled DSDTs I have here seem to use
> IRQNoFlags() for the interrupts, which apparently implies the
> interrupt is edge-triggered.
> 
> Let me see if I can cook a diff.

Updated diff now that kettenis@ fixed parsing of the irq flags.

diff --git share/man/man4/com.4 share/man/man4/com.4
index 73b421f2ca7..e54255fe0d6 100644
--- share/man/man4/com.4
+++ share/man/man4/com.4
@@ -61,11 +61,13 @@
 .Cd "com0 at isa? port 0x3f8 irq 4"
 .Cd "com1 at isa? port 0x2f8 irq 3"
 .Pp
+.Cd "# arm64 and amd64"
+.Cd "com* at acpi?"
+.Pp
 .Cd "# armv7"
 .Cd "com* at fdt?"
 .Pp
 .Cd "# arm64"
-.Cd "com* at acpi?"
 .Cd "com* at fdt?"
 .Pp
 .Cd "# hppa"
diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
index ecccd1323d9..87fcaced306 100644
--- sys/arch/amd64/conf/GENERIC
+++ sys/arch/amd64/conf/GENERIC
@@ -65,6 +65,11 @@ amdgpio* at acpi?
 aplgpio*   at acpi?
 bytgpio*   at acpi?
 chvgpio*   at acpi?
+com0   at acpi?
+com1   at acpi?
+com2   at acpi?
+com3   at acpi?
+com*   at acpi?
 glkgpio*   at acpi?
 pchgpio*   at acpi?
 sdhc*  at acpi?
diff --git sys/arch/amd64/conf/RAMDISK sys/arch/amd64/conf/RAMDISK
index 6041293b287..a5f10b357dd 100644
--- sys/arch/amd64/conf/RAMDISK
+++ sys/arch/amd64/conf/RAMDISK
@@ -34,6 +34,9 @@ acpipci*  at acpi?
 acpiprt*   at acpi?
 acpimadt0  at acpi?
 #acpitz*   at acpi?
+com0   at acpi?
+com1   at acpi?
+com*   at acpi?
 
 mpbios0at bios0
 
diff --git sys/arch/amd64/conf/RAMDISK_CD sys/arch/amd64/conf/RAMDISK_CD
index 8bd646b4ea3..d007c0102d0 100644
--- sys/arch/amd64/conf/RAMDISK_CD
+++ sys/arch/amd64/conf/RAMDISK_CD
@@ -51,6 +51,10 @@ bytgpio* at acpi?
 sdhc*  at acpi?
 acpihve*   at acpi?
 chvgpio*at acpi?
+com0   at acpi?
+com1   at acpi?
+com2   at acpi?
+com*   at acpi?
 glkgpio*   at acpi?
 
 mpbios0at bios0
diff --git sys/dev/acpi/acpi.c sys/dev/acpi/acpi.c
index 7577424e8a2..e89869aedbd 100644
--- sys/dev/acpi/acpi.c
+++ sys/dev/acpi/acpi.c
@@ -3140,7 +3140,6 @@ const char *acpi_isa_hids[] = {
"PNP0303",  /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */
"PNP0400",  /* Standard LPT Parallel Port */
"PNP0401",  /* ECP Parallel Port */
-   "PNP0501",  /* 16550A-compatible COM Serial Port */
"PNP0700",  /* PC-class Floppy Disk Controller */
"PNP0F03",  /* Microsoft PS/2-style Mouse */
"PNP0F13",  /* PS/2 Mouse */
diff --git sys/dev/acpi/com_acpi.c sys/dev/acpi/com_acpi.c
index 852be6c71b3..e4001861032 100644
--- sys/dev/acpi/com_acpi.c
+++ sys/dev/acpi/com_acpi.c
@@ -49,10 +49,12 @@ struct cfattach com_acpi_ca = {
 
 const

Re: com(4) at acpi(4) on amd64

2021-12-06 Thread Anton Lindqvist
On Mon, Dec 06, 2021 at 09:23:45PM +0100, Mark Kettenis wrote:
> > Date: Mon, 6 Dec 2021 21:08:04 +0100
> > From: Patrick Wildt 
> > 
> > Hi,
> > 
> > On one machine I had the pleasure of having to try and use the
> > Serial-over-LAN feature which shows up as just another com(4)
> > device.  Instead of having to manually add a com(4) at isa(4)
> > I figured it would be nicer to have them attach via ACPI.  At
> > least on that machine, the SOL definitely shows up in the DSDT.
> > 
> > Since I don't want to break any legacy machines, I figured I'd
> > keep ignoring the isa(4) addresses specified in amd64's GENERIC.
> > 
> > Right now this diff is more about putting it out there, not about
> > asking for OKs, as amd64 isn't really my strong suit.  If people
> > are interested, I can definitely put in all the feedback there is.
> > 
> > Patrick
> 
> anton@ has a better diff he's working on

Here's the diff in its current state. There's one thing I haven't had
the time to figure out yet: in order to get interrupts working on my
apu2 I had to explicit pass LR_EXTIRQ_MODE (aaa_irq_flags is zero) to
acpi_intr_establish() which causes IST_EDGE to be passed to
intr_establish(). Worth noting is that this matches what com at isa
already does. This was however not necessary on my amd64 build machine
where aaa_irq_flags also is zero.

Example attachment:

com0 at acpi0 UAR2 addr 0x3f8/0x8 irq 3: ns16550a, 16 byte fifo
com0: console

diff --git share/man/man4/com.4 share/man/man4/com.4
index 73b421f2ca7..e54255fe0d6 100644
--- share/man/man4/com.4
+++ share/man/man4/com.4
@@ -61,11 +61,13 @@
 .Cd "com0 at isa? port 0x3f8 irq 4"
 .Cd "com1 at isa? port 0x2f8 irq 3"
 .Pp
+.Cd "# arm64 and amd64"
+.Cd "com* at acpi?"
+.Pp
 .Cd "# armv7"
 .Cd "com* at fdt?"
 .Pp
 .Cd "# arm64"
-.Cd "com* at acpi?"
 .Cd "com* at fdt?"
 .Pp
 .Cd "# hppa"
diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
index ecccd1323d9..87fcaced306 100644
--- sys/arch/amd64/conf/GENERIC
+++ sys/arch/amd64/conf/GENERIC
@@ -65,6 +65,11 @@ amdgpio* at acpi?
 aplgpio*   at acpi?
 bytgpio*   at acpi?
 chvgpio*   at acpi?
+com0   at acpi?
+com1   at acpi?
+com2   at acpi?
+com3   at acpi?
+com*   at acpi?
 glkgpio*   at acpi?
 pchgpio*   at acpi?
 sdhc*  at acpi?
diff --git sys/arch/amd64/conf/RAMDISK sys/arch/amd64/conf/RAMDISK
index 6041293b287..a5f10b357dd 100644
--- sys/arch/amd64/conf/RAMDISK
+++ sys/arch/amd64/conf/RAMDISK
@@ -34,6 +34,9 @@ acpipci*  at acpi?
 acpiprt*   at acpi?
 acpimadt0  at acpi?
 #acpitz*   at acpi?
+com0   at acpi?
+com1   at acpi?
+com*   at acpi?
 
 mpbios0at bios0
 
diff --git sys/arch/amd64/conf/RAMDISK_CD sys/arch/amd64/conf/RAMDISK_CD
index 8bd646b4ea3..d007c0102d0 100644
--- sys/arch/amd64/conf/RAMDISK_CD
+++ sys/arch/amd64/conf/RAMDISK_CD
@@ -51,6 +51,10 @@ bytgpio* at acpi?
 sdhc*  at acpi?
 acpihve*   at acpi?
 chvgpio*at acpi?
+com0   at acpi?
+com1   at acpi?
+com2   at acpi?
+com*   at acpi?
 glkgpio*   at acpi?
 
 mpbios0at bios0
diff --git sys/dev/acpi/acpi.c sys/dev/acpi/acpi.c
index 7577424e8a2..e89869aedbd 100644
--- sys/dev/acpi/acpi.c
+++ sys/dev/acpi/acpi.c
@@ -3140,7 +3140,6 @@ const char *acpi_isa_hids[] = {
"PNP0303",  /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */
"PNP0400",  /* Standard LPT Parallel Port */
"PNP0401",  /* ECP Parallel Port */
-   "PNP0501",  /* 16550A-compatible COM Serial Port */
"PNP0700",  /* PC-class Floppy Disk Controller */
"PNP0F03",  /* Microsoft PS/2-style Mouse */
"PNP0F13",  /* PS/2 Mouse */
diff --git sys/dev/acpi/com_acpi.c sys/dev/acpi/com_acpi.c
index 852be6c71b3..be78e34a016 100644
--- sys/dev/acpi/com_acpi.c
+++ sys/dev/acpi/com_acpi.c
@@ -49,10 +49,12 @@ struct cfattach com_acpi_ca = {
 
 const char *com_hids[] = {
"HISI0031",
+   "PNP0501",
NULL
 };
 
 intcom_acpi_is_console(struct com_acpi_softc *);
+intcom_acpi_is_designware(const char *);
 intcom_acpi_intr_designware(void *);
 
 int
@@ -69,7 +71,7 @@ com_acpi_attach(struct device *parent, struct device *self, 
void *aux)
 {
struct com_acpi_softc *sc = (struct com_acpi_softc *)self;
struct acpi_attach_args *aaa = aux;
-   uint32_t freq;
+   int (*intrfn)(void *) = comintr;
 
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_node = aaa->aaa_node;
@@ -85,34 +87,44 @@ com_acpi_attach(struct device *parent, struct device *self, 
void *aux)
return;
}
 
-   printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]);
+   printf(" addr 0x%llx/%llu", aaa->aaa_addr[0], aaa->aaa_size[0]);
printf(" irq %d", aaa->aaa_irq[0]);
 
-   freq = acpi_getpropint(sc->sc_node, "clock-frequency", 0);
-
 

usbd_new_device: consolidate error paths

2021-12-02 Thread Anton Lindqvist
Hi,
Consolidate error paths in usbd_new_device, shaving of 14 lines.

Comments? OK?

diff --git sys/dev/usb/usb_subr.c sys/dev/usb/usb_subr.c
index a11bc448ece..74fe4c3b4db 100644
--- sys/dev/usb/usb_subr.c
+++ sys/dev/usb/usb_subr.c
@@ -1086,11 +1086,8 @@ usbd_new_device(struct device *parent, struct usbd_bus 
*bus, int depth,
/* Establish the default pipe. */
err = usbd_setup_pipe(dev, 0, >def_ep, USBD_DEFAULT_INTERVAL,
>default_pipe);
-   if (err) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (err);
-   }
+   if (err)
+   goto fail;
 
dd = >ddesc;
 
@@ -1137,12 +1134,8 @@ usbd_new_device(struct device *parent, struct usbd_bus 
*bus, int depth,
USB_MAX_IPACKET, dd);
}
 
-   if (err) {
-fail:
-   usb_free_device(dev);
-   up->device = NULL;
-   return (err);
-   }
+   if (err)
+   goto fail;
 
DPRINTF(("%s: adding unit addr=%d, rev=%02x, class=%d, subclass=%d, "
 "protocol=%d, maxpacket=%d, len=%d, speed=%d\n", __func__,
@@ -1152,9 +1145,8 @@ fail:
 
if ((dd->bDescriptorType != UDESC_DEVICE) ||
(dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE)) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (USBD_INVAL);
+   err = USBD_INVAL;
+   goto fail;
}
 
mps = dd->bMaxPacketSize;
@@ -1168,9 +1160,8 @@ fail:
if (mps != mps0) {
if ((speed == USB_SPEED_LOW) ||
(mps != 8 && mps != 16 && mps != 32 && mps != 64)) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (USBD_INVAL);
+   err = USBD_INVAL;
+   goto fail;
}
USETW(dev->def_ep_desc.wMaxPacketSize, mps);
}
@@ -1179,9 +1170,8 @@ fail:
/* Set the address if the HC didn't do it already. */
if (bus->methods->dev_setaddr != NULL &&
bus->methods->dev_setaddr(dev, addr)) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (USBD_SET_ADDR_FAILED);
+   err = USBD_SET_ADDR_FAILED;
+   goto fail;
}
 
/* Wait for device to settle before reloading the descriptor. */
@@ -1194,11 +1184,8 @@ fail:
dev->address = addr;
 
err = usbd_reload_device_desc(dev);
-   if (err) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (err);
-   }
+   if (err)
+   goto fail;
 
/* send disown request to handover 2.0 to 1.1. */
if (dev->quirks->uq_flags & UQ_EHCI_NEEDTO_DISOWN) {
@@ -1222,22 +1209,21 @@ fail:
 
/* Get device info and cache it */
err = usbd_cache_devinfo(dev);
-   if (err) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (err);
-   }
+   if (err)
+   goto fail;
 
bus->devices[addr] = dev;
 
err = usbd_probe_and_attach(parent, dev, port, addr);
-   if (err) {
-   usb_free_device(dev);
-   up->device = NULL;
-   return (err);
-   }
+   if (err)
+   goto fail;
 
return (USBD_NORMAL_COMPLETION);
+
+fail:
+   usb_free_device(dev);
+   up->device = NULL;
+   return (err);
 }
 
 usbd_status



uhidev: stricter claim multiple report ids

2021-11-22 Thread Anton Lindqvist
Hi,
This will prevent a driver attaching on top of uhidev from doing the
wrong thing in response to a claim multiple report ids match request.
Returning non-zero from such request must imply that at least one report
id is claimed. This would have caught some of the uhidev problems fixed
at this point.

Comments? OK?

diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index 3526e4cb86e..258395af898 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -256,16 +256,21 @@ uhidev_attach(struct device *parent, struct device *self, 
void *aux)
/* Look for a driver claiming multiple report IDs first. */
dev = config_found_sm(self, , NULL, NULL);
if (dev != NULL) {
+   int nclaimed = 0;
+
for (repid = 0; repid < nrepid; repid++) {
+   if (!uha.claimed[repid])
+   continue;
+
+   nclaimed++;
/*
 * Could already be assigned by uhidev_set_report_dev().
 */
if (sc->sc_subdevs[repid] != NULL)
-   continue;
-
-   if (uha.claimed[repid])
sc->sc_subdevs[repid] = (struct uhidev *)dev;
}
+   KASSERTMSG(nclaimed > 0, "%s did not claim any report ids",
+   dev->dv_xname);
}
 
free(uha.claimed, M_TEMP, nrepid);



uhidev: missing claim multiple report ids

2021-11-16 Thread Anton Lindqvist
Hi,
Here are the last drivers missing a claim multiple report ids
conditional. None of them currently claims more than one report id.
With this is place, the old problematic approach of signalling
that multiple report ids should be claimed to the match routines using
__UHIDEV_CLAIM_MULTIPLE_REPORTID can be removed.

Comments? OK?

Index: sys/dev/usb/ukbd.c
===
RCS file: /cvs/src/sys/dev/usb/ukbd.c,v
retrieving revision 1.84
diff -u -p -r1.84 ukbd.c
--- sys/dev/usb/ukbd.c  12 Sep 2021 06:58:08 -  1.84
+++ sys/dev/usb/ukbd.c  17 Nov 2021 06:23:28 -
@@ -201,6 +201,9 @@ ukbd_match(struct device *parent, void *
int size;
void *desc;
 
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
+   return (UMATCH_NONE);
+
uhidev_get_report_desc(uha->parent, , );
if (!hid_is_collection(desc, size, uha->reportid,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
Index: sys/dev/usb/ums.c
===
RCS file: /cvs/src/sys/dev/usb/ums.c,v
retrieving revision 1.50
diff -u -p -r1.50 ums.c
--- sys/dev/usb/ums.c   12 Sep 2021 06:58:08 -  1.50
+++ sys/dev/usb/ums.c   17 Nov 2021 06:23:28 -
@@ -93,6 +93,9 @@ ums_match(struct device *parent, void *m
int size;
void *desc;
 
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
+   return (UMATCH_NONE);
+
uhidev_get_report_desc(uha->parent, , );
 
if (hid_is_collection(desc, size, uha->reportid,
Index: sys/dev/usb/umstc.c
===
RCS file: /cvs/src/sys/dev/usb/umstc.c,v
retrieving revision 1.6
diff -u -p -r1.6 umstc.c
--- sys/dev/usb/umstc.c 12 Sep 2021 06:58:08 -  1.6
+++ sys/dev/usb/umstc.c 17 Nov 2021 06:23:28 -
@@ -80,6 +80,9 @@ umstc_match(struct device *parent, void 
int size;
void *desc;
 
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
+   return (UMATCH_NONE);
+
if (!usb_lookup(umstc_devs, uha->uaa->vendor, uha->uaa->product))
return UMATCH_NONE;
 
Index: sys/dev/usb/utpms.c
===
RCS file: /cvs/src/sys/dev/usb/utpms.c,v
retrieving revision 1.11
diff -u -p -r1.11 utpms.c
--- sys/dev/usb/utpms.c 23 Oct 2020 21:23:58 -  1.11
+++ sys/dev/usb/utpms.c 17 Nov 2021 06:23:28 -
@@ -269,6 +269,9 @@ utpms_match(struct device *parent, void 
usb_interface_descriptor_t *id;
int i;
 
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
+   return (UMATCH_NONE);
+
id = usbd_get_interface_descriptor(uha->uaa->iface);
if (id == NULL ||
id->bInterfaceSubClass != UISUBCLASS_BOOT ||
Index: sys/dev/usb/uwacom.c
===
RCS file: /cvs/src/sys/dev/usb/uwacom.c,v
retrieving revision 1.4
diff -u -p -r1.4 uwacom.c
--- sys/dev/usb/uwacom.c12 Sep 2021 06:58:08 -  1.4
+++ sys/dev/usb/uwacom.c17 Nov 2021 06:23:28 -
@@ -75,6 +75,9 @@ uwacom_match(struct device *parent, void
int size;
void *desc;
 
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
+   return (UMATCH_NONE);
+
if (usb_lookup(uwacom_devs, uha->uaa->vendor,
uha->uaa->product) == NULL)
return (UMATCH_NONE);



Re: uhidev: claim multiple report ids [3/N]

2021-11-12 Thread Anton Lindqvist
On Thu, Nov 11, 2021 at 05:09:35PM -0800, Greg Steuck wrote:
> Anton Lindqvist  writes:
> 
> > On Thu, Nov 11, 2021 at 03:29:15PM +0100, Anton Lindqvist wrote:
> >> Hi,
> >> The second attempt to solve the uhidev claim multiple report ids
> >> conflict didn't work out either as it broke fido(4). Signalling claim
> >> multiple report ids to the match routines using the report id does not
> >> work as all 256 values already have semantic meaning. I instead want to
> >> use `uha->claimed != NULL' to signal that multiple report ids can be
> >> claimed. Before doing so, refactor in order to make an upcoming diff
> >> with the actual fix significantly smaller.
> >> 
> >> No intended^W functional change.
> >> 
> >> Comments? OK?
> >
> > ... and here's the actual fix applied on top of the previous diff.
> 
> The pair of diffs seems to work for me (fido remains operational unlike
> the previous iteration). There's a minor change in dmesg output which is
> not otherwise consequential:

Thanks, some drivers (ums and ukbd for instance) are still missing a
UHIDEV_CLAIM_MULTIPLE_REPORTID conditional. That can be fixed later on.
For now, keep using 255 as the report id when claiming multiple report
ids.

Here's a new iteration of the second diff. Another round of testing
would be much appreciated.

diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
index 86217fb8880..b8daf014662 100644
--- sys/dev/usb/uhidev.h
+++ sys/dev/usb/uhidev.h
@@ -75,12 +75,11 @@ struct uhidev_attach_arg {
struct usb_attach_arg   *uaa;
struct uhidev_softc *parent;
uint8_t  reportid;
-   uint8_t  nreports;
+   u_intnreports;
uint8_t *claimed;
 };
 
-#define UHIDEV_CLAIM_MULTIPLE_REPORTID(u) \
-   ((u)->reportid == __UHIDEV_CLAIM_MULTIPLE_REPORTID)
+#define UHIDEV_CLAIM_MULTIPLE_REPORTID(u)  ((u)->claimed != NULL)
 #define__UHIDEV_CLAIM_MULTIPLE_REPORTID255 /* XXX */
 
 int uhidev_report_type_conv(int);



Re: uhidev: claim multiple report ids [3/N]

2021-11-11 Thread Anton Lindqvist
On Thu, Nov 11, 2021 at 03:29:15PM +0100, Anton Lindqvist wrote:
> Hi,
> The second attempt to solve the uhidev claim multiple report ids
> conflict didn't work out either as it broke fido(4). Signalling claim
> multiple report ids to the match routines using the report id does not
> work as all 256 values already have semantic meaning. I instead want to
> use `uha->claimed != NULL' to signal that multiple report ids can be
> claimed. Before doing so, refactor in order to make an upcoming diff
> with the actual fix significantly smaller.
> 
> No intended^W functional change.
> 
> Comments? OK?

... and here's the actual fix applied on top of the previous diff.

diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index 60d1874322a..eb9bc927670 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -248,7 +248,7 @@ uhidev_attach(struct device *parent, struct device *self, 
void *aux)
 
uha.uaa = uaa;
uha.parent = sc;
-   uha.reportid = __UHIDEV_CLAIM_MULTIPLE_REPORTID;
+   uha.reportid = 0;
uha.nreports = nrepid;
uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
 
@@ -360,7 +360,7 @@ uhidevprint(void *aux, const char *pnp)
 
if (pnp)
printf("uhid at %s", pnp);
-   if (uha->reportid != 0 && uha->reportid != 
__UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (uha->reportid != 0)
printf(" reportid %d", uha->reportid);
return (UNCONF);
 }
diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
index 86217fb8880..fda59b2a139 100644
--- sys/dev/usb/uhidev.h
+++ sys/dev/usb/uhidev.h
@@ -75,13 +75,11 @@ struct uhidev_attach_arg {
struct usb_attach_arg   *uaa;
struct uhidev_softc *parent;
uint8_t  reportid;
-   uint8_t  nreports;
+   u_intnreports;
uint8_t *claimed;
 };
 
-#define UHIDEV_CLAIM_MULTIPLE_REPORTID(u) \
-   ((u)->reportid == __UHIDEV_CLAIM_MULTIPLE_REPORTID)
-#define__UHIDEV_CLAIM_MULTIPLE_REPORTID255 /* XXX */
+#define UHIDEV_CLAIM_MULTIPLE_REPORTID(u)  ((u)->claimed != NULL)
 
 int uhidev_report_type_conv(int);
 void uhidev_get_report_desc(struct uhidev_softc *, void **, int *);



uhidev: claim multiple report ids [3/N]

2021-11-11 Thread Anton Lindqvist
Hi,
The second attempt to solve the uhidev claim multiple report ids
conflict didn't work out either as it broke fido(4). Signalling claim
multiple report ids to the match routines using the report id does not
work as all 256 values already have semantic meaning. I instead want to
use `uha->claimed != NULL' to signal that multiple report ids can be
claimed. Before doing so, refactor in order to make an upcoming diff
with the actual fix significantly smaller.

No intended^W functional change.

Comments? OK?

diff --git sys/dev/usb/fido.c sys/dev/usb/fido.c
index c6d846aaa84..0232694b55a 100644
--- sys/dev/usb/fido.c
+++ sys/dev/usb/fido.c
@@ -63,7 +63,7 @@ fido_match(struct device *parent, void *match, void *aux)
void *desc;
int   ret = UMATCH_NONE;
 
-   if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (ret);
 
/* Find the FIDO usage page and U2F collection */
diff --git sys/dev/usb/ucycom.c sys/dev/usb/ucycom.c
index ca8636f0a7f..621f6af2d5d 100644
--- sys/dev/usb/ucycom.c
+++ sys/dev/usb/ucycom.c
@@ -165,7 +165,7 @@ ucycom_match(struct device *parent, void *match, void *aux)
 {
struct uhidev_attach_arg *uha = aux;
 
-   if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (UMATCH_NONE);
 
return (usb_lookup(ucycom_devs, uha->uaa->vendor, uha->uaa->product) != 
NULL ?
diff --git sys/dev/usb/ugold.c sys/dev/usb/ugold.c
index b83d8edd8e8..aafaa1712cc 100644
--- sys/dev/usb/ugold.c
+++ sys/dev/usb/ugold.c
@@ -113,7 +113,7 @@ ugold_match(struct device *parent, void *match, void *aux)
int size;
void *desc;
 
-   if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (UMATCH_NONE);
 
if (usb_lookup(ugold_devs, uha->uaa->vendor, uha->uaa->product) == NULL)
diff --git sys/dev/usb/uhid.c sys/dev/usb/uhid.c
index 90a75d878e3..c2f97dd833a 100644
--- sys/dev/usb/uhid.c
+++ sys/dev/usb/uhid.c
@@ -115,7 +115,7 @@ uhid_match(struct device *parent, void *match, void *aux)
 {
struct uhidev_attach_arg *uha = aux;
 
-   if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (UMATCH_NONE);
 
return (UMATCH_IFACECLASS_GENERIC);
diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index 3ce1684893b..60d1874322a 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -248,7 +248,7 @@ uhidev_attach(struct device *parent, struct device *self, 
void *aux)
 
uha.uaa = uaa;
uha.parent = sc;
-   uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
+   uha.reportid = __UHIDEV_CLAIM_MULTIPLE_REPORTID;
uha.nreports = nrepid;
uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
 
@@ -360,7 +360,7 @@ uhidevprint(void *aux, const char *pnp)
 
if (pnp)
printf("uhid at %s", pnp);
-   if (uha->reportid != 0 && uha->reportid != 
UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (uha->reportid != 0 && uha->reportid != 
__UHIDEV_CLAIM_MULTIPLE_REPORTID)
printf(" reportid %d", uha->reportid);
return (UNCONF);
 }
diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
index b2b7608b083..86217fb8880 100644
--- sys/dev/usb/uhidev.h
+++ sys/dev/usb/uhidev.h
@@ -75,11 +75,14 @@ struct uhidev_attach_arg {
struct usb_attach_arg   *uaa;
struct uhidev_softc *parent;
uint8_t  reportid;
-#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  255
uint8_t  nreports;
uint8_t *claimed;
 };
 
+#define UHIDEV_CLAIM_MULTIPLE_REPORTID(u) \
+   ((u)->reportid == __UHIDEV_CLAIM_MULTIPLE_REPORTID)
+#define__UHIDEV_CLAIM_MULTIPLE_REPORTID255 /* XXX */
+
 int uhidev_report_type_conv(int);
 void uhidev_get_report_desc(struct uhidev_softc *, void **, int *);
 int uhidev_open(struct uhidev *);
diff --git sys/dev/usb/ujoy.c sys/dev/usb/ujoy.c
index ca461e5969a..11d77f9daba 100644
--- sys/dev/usb/ujoy.c
+++ sys/dev/usb/ujoy.c
@@ -104,7 +104,7 @@ ujoy_match(struct device *parent, void *match, void *aux)
void *desc;
int   ret = UMATCH_NONE;
 
-   if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID)
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (ret);
 
/* Find the general usage page and gamecontroller collections */
diff --git sys/dev/usb/umt.c sys/dev/usb/umt.c
index 3aa45bf298a..0915b38de5c 100644
--- sys/dev/usb/umt.c
+++ sys/dev/usb/umt.c
@@ -90,7 +90,7 @@ umt_match(struct device *parent, void *match, void *aux)
int size;
void *desc;
 
-   if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) {
+   if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)) {
   

Re: uhidev: claim multiple report ids

2021-11-09 Thread Anton Lindqvist
On Wed, Nov 03, 2021 at 09:43:54AM +0100, Damien Couderc wrote:
> Le 03/11/2021 à 07:44, Anton Lindqvist a écrit :
> > Hi,
> > In an attempt to fix a bug related to upd(4) I discovered that the
> > pseudo report id UHIDEV_CLAIM_MULTIPLE_REPORTID is conflicting with an
> > actual report id. The previous fix, reverted by now, avoided the
> > conflict by incrementing the pseudo report id was not a good idea
> > since a report id is expected to be represented using a single unsigned
> > byte elsewhere in the usb stack.
> > 
> > Here's a second attempt. Report id zero is according to the USB HID
> > specification reserved and should not be used. We can define
> > UHIDEV_CLAIM_MULTIPLE_REPORTID as zero removing the need to use a larger
> > integer type than the existing uint8_t for the report id. Another
> > correction is also needed. Some descriptors only supports a single
> > report and the report id is in this case optional. Internally, uhidev
> > uses report id zero for such devices. It's therefore of importance to
> > not perform a claim multiple report ids attachment on such devices as
> > there's only one report id to claim.
> > 
> > Testing would be much appreciated.
> > 
> > Comments? OK?
> > 
> > diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
> > index 5fe2f702e21..f5cc5984b59 100644
> > --- sys/dev/usb/uhidev.c
> > +++ sys/dev/usb/uhidev.c
> > @@ -247,29 +247,36 @@ uhidev_attach(struct device *parent, struct device 
> > *self, void *aux)
> > sc->sc_isize += (nrepid != 1);  /* one byte for the report ID */
> > DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
> > +   memset(, 0, sizeof(uha));
> > uha.uaa = uaa;
> > uha.parent = sc;
> > -   uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
> > -   uha.nreports = nrepid;
> > -   uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
> > /* Look for a driver claiming multiple report IDs first. */
> > -   dev = config_found_sm(self, , NULL, uhidevsubmatch);
> > -   if (dev != NULL) {
> > -   for (repid = 0; repid < nrepid; repid++) {
> > -   /*
> > -* Could already be assigned by uhidev_set_report_dev().
> > -*/
> > -   if (sc->sc_subdevs[repid] != NULL)
> > -   continue;
> > -
> > -   if (uha.claimed[repid])
> > +   if (nrepid > 1) {
> > +   uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
> > +   uha.nreports = nrepid;
> > +   uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
> > +
> > +   dev = config_found_sm(self, , NULL, uhidevsubmatch);
> > +   if (dev != NULL) {
> > +   for (repid = 0; repid < nrepid; repid++) {
> > +   /*
> > +* Could already be assigned by
> > +* uhidev_set_report_dev().
> > +*/
> > +   if (sc->sc_subdevs[repid] != NULL)
> > +   continue;
> > +
> > +   if (!uha.claimed[repid])
> > +   continue;
> > sc->sc_subdevs[repid] = (struct uhidev *)dev;
> > +   }
> > }
> > -   }
> > -   free(uha.claimed, M_TEMP, nrepid);
> > -   uha.claimed = NULL;
> > +   free(uha.claimed, M_TEMP, nrepid);
> > +   uha.nreports = 0;
> > +   uha.claimed = NULL;
> > +   }
> > for (repid = 0; repid < nrepid; repid++) {
> > DPRINTF(("%s: try repid=%d\n", __func__, repid));
> > diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
> > index 6ce75b1f49d..9ae85e1ab9f 100644
> > --- sys/dev/usb/uhidev.h
> > +++ sys/dev/usb/uhidev.h
> > @@ -81,8 +81,8 @@ struct uhidev_attach_arg {
> > struct usb_attach_arg   *uaa;
> > struct uhidev_softc *parent;
> > uint8_t  reportid;
> > -#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  255
> > -   uint8_t  nreports;
> > +#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  0
> > +   u_intnreports;
> > uint8_t *claimed;
> >   };
> 
> Hi,
> 
> It works flawlessly for me and unplugging is fine too.

Thanks, committed.



uhidev: remove unused code

2021-11-07 Thread Anton Lindqvist
Hi,
The uhidevsubmatch() routine was imported from NetBSD back in 2002[1] along with
the reportid locator. The same locator was removed in 2004[2] making
this routine and its defines redundant.

Comments? OK?

[1] 
https://github.com/openbsd/src/commit/a66cb31e58a16ed957a52ce1b92aafc08fc4900d
[2] 
https://github.com/openbsd/src/commit/cd0cdd200650f714bb35984fcf257b23b34b6f39

diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index b56c00ceceb..d4bd3c5fef9 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -89,7 +89,6 @@ void uhidev_intr(struct usbd_xfer *, void *, usbd_status);
 
 int uhidev_maxrepid(void *buf, int len);
 int uhidevprint(void *aux, const char *pnp);
-int uhidevsubmatch(struct device *parent, void *cf, void *aux);
 
 int uhidev_match(struct device *, void *, void *);
 void uhidev_attach(struct device *, struct device *, void *);
@@ -257,7 +256,7 @@ uhidev_attach(struct device *parent, struct device *self, 
void *aux)
uha.nreports = nrepid;
uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
 
-   dev = config_found_sm(self, , NULL, uhidevsubmatch);
+   dev = config_found_sm(self, , NULL, NULL);
if (dev != NULL) {
for (repid = 0; repid < nrepid; repid++) {
/*
@@ -290,7 +289,7 @@ uhidev_attach(struct device *parent, struct device *self, 
void *aux)
continue;
 
uha.reportid = repid;
-   dev = config_found_sm(self, , uhidevprint, uhidevsubmatch);
+   dev = config_found_sm(self, , uhidevprint, NULL);
sc->sc_subdevs[repid] = (struct uhidev *)dev;
}
 }
@@ -373,17 +372,6 @@ uhidevprint(void *aux, const char *pnp)
return (UNCONF);
 }
 
-int uhidevsubmatch(struct device *parent, void *match, void *aux)
-{
-   struct uhidev_attach_arg *uha = aux;
-struct cfdata *cf = match;
-
-   if (cf->uhidevcf_reportid != UHIDEV_UNK_REPORTID &&
-   cf->uhidevcf_reportid != uha->reportid)
-   return (0);
-   return ((*cf->cf_attach->ca_match)(parent, cf, aux));
-}
-
 int
 uhidev_activate(struct device *self, int act)
 {
diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
index 9ae85e1ab9f..104fe59c8aa 100644
--- sys/dev/usb/uhidev.h
+++ sys/dev/usb/uhidev.h
@@ -31,12 +31,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define UHIDBUSCF_REPORTID 0
-#define UHIDBUSCF_REPORTID_DEFAULT -1
-
-#define uhidevcf_reportid cf_loc[UHIDBUSCF_REPORTID]
-#define UHIDEV_UNK_REPORTID UHIDBUSCF_REPORTID_DEFAULT
-
 struct uhidev_softc {
struct device sc_dev;   /* base device */
struct usbd_device *sc_udev;



uhidev: plug memory leak

2021-11-03 Thread Anton Lindqvist
Hi,
Upon uhidev detach, free the list of sub devices.

Comments? OK?

diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index 014dc052c1c..5fe2f702e21 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -451,6 +451,7 @@ uhidev_detach(struct device *self, int flags)
 
sc->sc_subdevs[i] = NULL;
}
+   free(sc->sc_subdevs, M_USBDEV, sc->sc_nrepid * sizeof(struct uhidev *));
 
return (rv);
 }



uhidev: claim multiple report ids

2021-11-03 Thread Anton Lindqvist
Hi,
In an attempt to fix a bug related to upd(4) I discovered that the
pseudo report id UHIDEV_CLAIM_MULTIPLE_REPORTID is conflicting with an
actual report id. The previous fix, reverted by now, avoided the
conflict by incrementing the pseudo report id was not a good idea
since a report id is expected to be represented using a single unsigned
byte elsewhere in the usb stack.

Here's a second attempt. Report id zero is according to the USB HID
specification reserved and should not be used. We can define
UHIDEV_CLAIM_MULTIPLE_REPORTID as zero removing the need to use a larger
integer type than the existing uint8_t for the report id. Another
correction is also needed. Some descriptors only supports a single
report and the report id is in this case optional. Internally, uhidev
uses report id zero for such devices. It's therefore of importance to
not perform a claim multiple report ids attachment on such devices as
there's only one report id to claim.

Testing would be much appreciated.

Comments? OK?

diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index 5fe2f702e21..f5cc5984b59 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -247,29 +247,36 @@ uhidev_attach(struct device *parent, struct device *self, 
void *aux)
sc->sc_isize += (nrepid != 1);  /* one byte for the report ID */
DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
 
+   memset(, 0, sizeof(uha));
uha.uaa = uaa;
uha.parent = sc;
-   uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
-   uha.nreports = nrepid;
-   uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
 
/* Look for a driver claiming multiple report IDs first. */
-   dev = config_found_sm(self, , NULL, uhidevsubmatch);
-   if (dev != NULL) {
-   for (repid = 0; repid < nrepid; repid++) {
-   /*
-* Could already be assigned by uhidev_set_report_dev().
-*/
-   if (sc->sc_subdevs[repid] != NULL)
-   continue;
-
-   if (uha.claimed[repid])
+   if (nrepid > 1) {
+   uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
+   uha.nreports = nrepid;
+   uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
+
+   dev = config_found_sm(self, , NULL, uhidevsubmatch);
+   if (dev != NULL) {
+   for (repid = 0; repid < nrepid; repid++) {
+   /*
+* Could already be assigned by
+* uhidev_set_report_dev().
+*/
+   if (sc->sc_subdevs[repid] != NULL)
+   continue;
+
+   if (!uha.claimed[repid])
+   continue;
sc->sc_subdevs[repid] = (struct uhidev *)dev;
+   }
}
-   }
 
-   free(uha.claimed, M_TEMP, nrepid);
-   uha.claimed = NULL;
+   free(uha.claimed, M_TEMP, nrepid);
+   uha.nreports = 0;
+   uha.claimed = NULL;
+   }
 
for (repid = 0; repid < nrepid; repid++) {
DPRINTF(("%s: try repid=%d\n", __func__, repid));
diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
index 6ce75b1f49d..9ae85e1ab9f 100644
--- sys/dev/usb/uhidev.h
+++ sys/dev/usb/uhidev.h
@@ -81,8 +81,8 @@ struct uhidev_attach_arg {
struct usb_attach_arg   *uaa;
struct uhidev_softc *parent;
uint8_t  reportid;
-#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  255
-   uint8_t  nreports;
+#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  0
+   u_intnreports;
uint8_t *claimed;
 };
 



Re: upd(4) page fault since 7.0

2021-10-29 Thread Anton Lindqvist
On Fri, Oct 29, 2021 at 08:56:36AM +0200, Damien Couderc wrote:
> Le 28/10/2021 à 21:09, Anton Lindqvist a écrit :
> 
> 
> Hi Anton,
> 
> It works great!
> 
> See below the resulting dmesg with option UPD_DEBUG.
> 
> Any chance this fix will come through syspatch?

I just committed a slightly tweaked version as
UHIDEV_CLAIM_MULTIPLE_REPORTID can be defined to 256 to avoid the
conflict according to the USB HID specification.

This will soon be available in -current snapshots.

Index: dev/usb/uhidev.h
===
RCS file: /cvs/src/sys/dev/usb/uhidev.h,v
retrieving revision 1.32
diff -u -p -r1.32 uhidev.h
--- dev/usb/uhidev.h12 Sep 2021 06:58:08 -  1.32
+++ dev/usb/uhidev.h29 Oct 2021 15:35:43 -
@@ -80,9 +80,9 @@ struct uhidev {
 struct uhidev_attach_arg {
struct usb_attach_arg   *uaa;
struct uhidev_softc *parent;
-   uint8_t  reportid;
-#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  255
-   uint8_t  nreports;
+   u_intreportid;
+#defineUHIDEV_CLAIM_MULTIPLE_REPORTID  256
+   u_intnreports;
uint8_t *claimed;
 };
 



Re: upd(4) page fault since 7.0

2021-10-28 Thread Anton Lindqvist
On Thu, Oct 28, 2021 at 08:40:03PM +0200, Anton Lindqvist wrote:
> On Thu, Oct 28, 2021 at 08:08:36PM +0200, Damien Couderc wrote:
> > Le 26/10/2021 à 19:03, Anton Lindqvist a écrit :
> > > On Tue, Oct 26, 2021 at 05:58:12PM +0200, Damien Couderc wrote:
> > > > Le 26/10/2021 à 16:11, Anton Lindqvist a écrit :
> > > > > On Tue, Oct 26, 2021 at 09:50:41AM +0200, Damien Couderc wrote:
> > > > > > Le 24/10/2021 à 21:45, Anton Lindqvist a écrit :
> > > > > > > On Sun, Oct 24, 2021 at 03:03:01PM +0200, Damien Couderc wrote:
> > > > > > > > Hi,
> > > > > > > > I got a page fault with upd(4) since 7.0.
> > > > > > > > 
> > > > > > > > The problem began with the last revision of upd.c (1.30):
> > > > > > > > 
> > > > > > > > ===
> > > > > > > > RCS file: /cvs/src/sys/dev/usb/upd.c,v
> > > > > > > > retrieving revision 1.29
> > > > > > > > retrieving revision 1.30
> > > > > > > > diff -u -r1.29 -r1.30
> > > > > > > > --- src/sys/dev/usb/upd.c   2021/03/08 14:35:57 1.29
> > > > > > > > +++ src/sys/dev/usb/upd.c   2021/08/06 17:46:45 1.30
> > > > > > > > @@ -1,4 +1,4 @@
> > > > > > > > -/* $OpenBSD: upd.c,v 1.29 2021/03/08 14:35:57 jcs Exp $ */
> > > > > > > > +/* $OpenBSD: upd.c,v 1.30 2021/08/06 17:46:45 abieber Exp 
> > > > > > > > $ */
> > > > > > > > 
> > > > > > > > /*
> > > > > > > >  * Copyright (c) 2015 David Higgs 
> > > > > > > > @@ -167,7 +167,7 @@
> > > > > > > > if (upd_lookup_usage_entry(desc, size,
> > > > > > > > upd_usage_roots + i, )) {
> > > > > > > > ret = UMATCH_VENDOR_PRODUCT;
> > > > > > > > -   break;
> > > > > > > > +   uha->claimed[item.report_ID] = 1;
> > > > > > > > }
> > > > > > > > 
> > > > > > > > return (ret);
> > > > > > > > 
> > > > > > > > ===
> > > > > > > > 
> > > > > > > > The uha.claimed array is allocated using uha.nreports as its 
> > > > > > > > size while
> > > > > > > > upd_match() is looping through the number of items of 
> > > > > > > > upd_usage_roots.
> > > > > > > > 
> > > > > > > > In my case uha.nreports is equal to zero so uha.claimed is 
> > > > > > > > null, hence
> > > > > > > > setting uha->claimed[n] is failing.
> > > > > > > > 
> > > > > > > > As I'm not familiar with the HID code I did not yet understood 
> > > > > > > > the
> > > > > > > > relation between upd_usage_roots and the claimed array but as 
> > > > > > > > we're
> > > > > > > > talking about UPS attached computers I though the issue would 
> > > > > > > > sensible
> > > > > > > > enough to make a quick reporting.
> > > > > > > > 
> > > > > > > > You'll find a dmesg with options UPD_DEBUG and UHIDEV_DEBUG set 
> > > > > > > > and the
> > > > > > > > following patch applied to circumvent the page fault and 
> > > > > > > > provide some debug:
> > > > > > > Could you try the following diff, looks like an unsigned wrap 
> > > > > > > around.
> > > > > > > 
> > > > > > > Index: dev/usb/uhidev.h
> > > > > > > ===
> > > > > > > RCS file: /cvs/src/sys/dev/usb/uhidev.h,v
> > > > > > > retrieving revision 1.32
> > > > > > > diff -u -p -r1.32 uhidev.h
> > > > > > > --- dev/usb/uhidev.h  12 Sep 2021 06:58:08 -  1.32
> > > > > > >

Re: upd(4) page fault since 7.0

2021-10-28 Thread Anton Lindqvist
On Thu, Oct 28, 2021 at 08:08:36PM +0200, Damien Couderc wrote:
> Le 26/10/2021 à 19:03, Anton Lindqvist a écrit :
> > On Tue, Oct 26, 2021 at 05:58:12PM +0200, Damien Couderc wrote:
> > > Le 26/10/2021 à 16:11, Anton Lindqvist a écrit :
> > > > On Tue, Oct 26, 2021 at 09:50:41AM +0200, Damien Couderc wrote:
> > > > > Le 24/10/2021 à 21:45, Anton Lindqvist a écrit :
> > > > > > On Sun, Oct 24, 2021 at 03:03:01PM +0200, Damien Couderc wrote:
> > > > > > > Hi,
> > > > > > > I got a page fault with upd(4) since 7.0.
> > > > > > > 
> > > > > > > The problem began with the last revision of upd.c (1.30):
> > > > > > > 
> > > > > > > ===
> > > > > > > RCS file: /cvs/src/sys/dev/usb/upd.c,v
> > > > > > > retrieving revision 1.29
> > > > > > > retrieving revision 1.30
> > > > > > > diff -u -r1.29 -r1.30
> > > > > > > --- src/sys/dev/usb/upd.c 2021/03/08 14:35:57 1.29
> > > > > > > +++ src/sys/dev/usb/upd.c 2021/08/06 17:46:45 1.30
> > > > > > > @@ -1,4 +1,4 @@
> > > > > > > -/*   $OpenBSD: upd.c,v 1.29 2021/03/08 14:35:57 jcs Exp $ */
> > > > > > > +/*   $OpenBSD: upd.c,v 1.30 2021/08/06 17:46:45 abieber Exp 
> > > > > > > $ */
> > > > > > > 
> > > > > > > /*
> > > > > > >  * Copyright (c) 2015 David Higgs 
> > > > > > > @@ -167,7 +167,7 @@
> > > > > > >   if (upd_lookup_usage_entry(desc, size,
> > > > > > >   upd_usage_roots + i, )) {
> > > > > > >   ret = UMATCH_VENDOR_PRODUCT;
> > > > > > > - break;
> > > > > > > + uha->claimed[item.report_ID] = 1;
> > > > > > >   }
> > > > > > > 
> > > > > > >   return (ret);
> > > > > > > 
> > > > > > > ===
> > > > > > > 
> > > > > > > The uha.claimed array is allocated using uha.nreports as its size 
> > > > > > > while
> > > > > > > upd_match() is looping through the number of items of 
> > > > > > > upd_usage_roots.
> > > > > > > 
> > > > > > > In my case uha.nreports is equal to zero so uha.claimed is null, 
> > > > > > > hence
> > > > > > > setting uha->claimed[n] is failing.
> > > > > > > 
> > > > > > > As I'm not familiar with the HID code I did not yet understood the
> > > > > > > relation between upd_usage_roots and the claimed array but as 
> > > > > > > we're
> > > > > > > talking about UPS attached computers I though the issue would 
> > > > > > > sensible
> > > > > > > enough to make a quick reporting.
> > > > > > > 
> > > > > > > You'll find a dmesg with options UPD_DEBUG and UHIDEV_DEBUG set 
> > > > > > > and the
> > > > > > > following patch applied to circumvent the page fault and provide 
> > > > > > > some debug:
> > > > > > Could you try the following diff, looks like an unsigned wrap 
> > > > > > around.
> > > > > > 
> > > > > > Index: dev/usb/uhidev.h
> > > > > > ===
> > > > > > RCS file: /cvs/src/sys/dev/usb/uhidev.h,v
> > > > > > retrieving revision 1.32
> > > > > > diff -u -p -r1.32 uhidev.h
> > > > > > --- dev/usb/uhidev.h12 Sep 2021 06:58:08 -  1.32
> > > > > > +++ dev/usb/uhidev.h24 Oct 2021 19:44:52 -
> > > > > > @@ -82,7 +82,7 @@ struct uhidev_attach_arg {
> > > > > > struct uhidev_softc *parent;
> > > > > > uint8_t  reportid;
> > > > > > #define UHIDEV_CLAIM_MULTIPLE_REPORTID  255
> > > > > > -   uint8_t  nreports;
> > > > >

Re: upd(4) page fault since 7.0

2021-10-26 Thread Anton Lindqvist
On Tue, Oct 26, 2021 at 05:58:12PM +0200, Damien Couderc wrote:
> Le 26/10/2021 à 16:11, Anton Lindqvist a écrit :
> > On Tue, Oct 26, 2021 at 09:50:41AM +0200, Damien Couderc wrote:
> > > Le 24/10/2021 à 21:45, Anton Lindqvist a écrit :
> > > > On Sun, Oct 24, 2021 at 03:03:01PM +0200, Damien Couderc wrote:
> > > > > Hi,
> > > > > I got a page fault with upd(4) since 7.0.
> > > > > 
> > > > > The problem began with the last revision of upd.c (1.30):
> > > > > 
> > > > > ===
> > > > > RCS file: /cvs/src/sys/dev/usb/upd.c,v
> > > > > retrieving revision 1.29
> > > > > retrieving revision 1.30
> > > > > diff -u -r1.29 -r1.30
> > > > > --- src/sys/dev/usb/upd.c 2021/03/08 14:35:57 1.29
> > > > > +++ src/sys/dev/usb/upd.c 2021/08/06 17:46:45 1.30
> > > > > @@ -1,4 +1,4 @@
> > > > > -/*   $OpenBSD: upd.c,v 1.29 2021/03/08 14:35:57 jcs Exp $ */
> > > > > +/*   $OpenBSD: upd.c,v 1.30 2021/08/06 17:46:45 abieber Exp $ */
> > > > > 
> > > > >/*
> > > > > * Copyright (c) 2015 David Higgs 
> > > > > @@ -167,7 +167,7 @@
> > > > >   if (upd_lookup_usage_entry(desc, size,
> > > > >   upd_usage_roots + i, )) {
> > > > >   ret = UMATCH_VENDOR_PRODUCT;
> > > > > - break;
> > > > > + uha->claimed[item.report_ID] = 1;
> > > > >   }
> > > > > 
> > > > >   return (ret);
> > > > > 
> > > > > ===
> > > > > 
> > > > > The uha.claimed array is allocated using uha.nreports as its size 
> > > > > while
> > > > > upd_match() is looping through the number of items of upd_usage_roots.
> > > > > 
> > > > > In my case uha.nreports is equal to zero so uha.claimed is null, hence
> > > > > setting uha->claimed[n] is failing.
> > > > > 
> > > > > As I'm not familiar with the HID code I did not yet understood the
> > > > > relation between upd_usage_roots and the claimed array but as we're
> > > > > talking about UPS attached computers I though the issue would sensible
> > > > > enough to make a quick reporting.
> > > > > 
> > > > > You'll find a dmesg with options UPD_DEBUG and UHIDEV_DEBUG set and 
> > > > > the
> > > > > following patch applied to circumvent the page fault and provide some 
> > > > > debug:
> > > > Could you try the following diff, looks like an unsigned wrap around.
> > > > 
> > > > Index: dev/usb/uhidev.h
> > > > ===
> > > > RCS file: /cvs/src/sys/dev/usb/uhidev.h,v
> > > > retrieving revision 1.32
> > > > diff -u -p -r1.32 uhidev.h
> > > > --- dev/usb/uhidev.h12 Sep 2021 06:58:08 -  1.32
> > > > +++ dev/usb/uhidev.h24 Oct 2021 19:44:52 -
> > > > @@ -82,7 +82,7 @@ struct uhidev_attach_arg {
> > > > struct uhidev_softc *parent;
> > > > uint8_t  reportid;
> > > >#define  UHIDEV_CLAIM_MULTIPLE_REPORTID  255
> > > > -   uint8_t  nreports;
> > > > +   u_intnreports;
> > > > uint8_t *claimed;
> > > >};
> > > > 
> > > Hello Anton,
> > > 
> > > I made a quick test and nreports is now set with 256 but I still get the
> > > page fault.
> > > 
> > > I'll check the details ASAP.
> > 
> > Do you have a backtrace?
> > 
> 
> I only have screenshots of ddb.
> 
> With the default kernel :
> http://cromagnon.petrocore.eu/ss_upd_ddb_default.jpg
> 
> With a custom kernel for a bit more data :
> http://cromagnon.petrocore.eu/ss_upd_ddb_custom.jpg

Looks like a NULL deref. My guess would be item.report_ID going out of
bounds on uha->claimed. Inspecting item.report_ID could provide some
hints. This in turn could be caused by uhidev_maxrepid() looking for
hid_none items whereas upd_lookup_usage_entry() uses hid_feature.

Also, it would be interesting to see the descriptor of this device. If
you make upd_match() unconditionally return 0 it should hopefully^W
attach as uhid device; making it possible to extract the report using
usbhidctl replacing X with the attached device:

# usbhidctl -R -f /dev/uhidX



Re: upd(4) page fault since 7.0

2021-10-26 Thread Anton Lindqvist
On Tue, Oct 26, 2021 at 09:50:41AM +0200, Damien Couderc wrote:
> Le 24/10/2021 à 21:45, Anton Lindqvist a écrit :
> > On Sun, Oct 24, 2021 at 03:03:01PM +0200, Damien Couderc wrote:
> > > Hi,
> > > I got a page fault with upd(4) since 7.0.
> > > 
> > > The problem began with the last revision of upd.c (1.30):
> > > 
> > > ===
> > > RCS file: /cvs/src/sys/dev/usb/upd.c,v
> > > retrieving revision 1.29
> > > retrieving revision 1.30
> > > diff -u -r1.29 -r1.30
> > > --- src/sys/dev/usb/upd.c 2021/03/08 14:35:57 1.29
> > > +++ src/sys/dev/usb/upd.c 2021/08/06 17:46:45 1.30
> > > @@ -1,4 +1,4 @@
> > > -/*   $OpenBSD: upd.c,v 1.29 2021/03/08 14:35:57 jcs Exp $ */
> > > +/*   $OpenBSD: upd.c,v 1.30 2021/08/06 17:46:45 abieber Exp $ */
> > > 
> > >   /*
> > >* Copyright (c) 2015 David Higgs 
> > > @@ -167,7 +167,7 @@
> > >   if (upd_lookup_usage_entry(desc, size,
> > >   upd_usage_roots + i, )) {
> > >   ret = UMATCH_VENDOR_PRODUCT;
> > > - break;
> > > + uha->claimed[item.report_ID] = 1;
> > >   }
> > > 
> > >   return (ret);
> > > 
> > > ===
> > > 
> > > The uha.claimed array is allocated using uha.nreports as its size while
> > > upd_match() is looping through the number of items of upd_usage_roots.
> > > 
> > > In my case uha.nreports is equal to zero so uha.claimed is null, hence
> > > setting uha->claimed[n] is failing.
> > > 
> > > As I'm not familiar with the HID code I did not yet understood the
> > > relation between upd_usage_roots and the claimed array but as we're
> > > talking about UPS attached computers I though the issue would sensible
> > > enough to make a quick reporting.
> > > 
> > > You'll find a dmesg with options UPD_DEBUG and UHIDEV_DEBUG set and the
> > > following patch applied to circumvent the page fault and provide some 
> > > debug:
> > Could you try the following diff, looks like an unsigned wrap around.
> > 
> > Index: dev/usb/uhidev.h
> > ===
> > RCS file: /cvs/src/sys/dev/usb/uhidev.h,v
> > retrieving revision 1.32
> > diff -u -p -r1.32 uhidev.h
> > --- dev/usb/uhidev.h12 Sep 2021 06:58:08 -  1.32
> > +++ dev/usb/uhidev.h24 Oct 2021 19:44:52 -
> > @@ -82,7 +82,7 @@ struct uhidev_attach_arg {
> > struct uhidev_softc *parent;
> > uint8_t  reportid;
> >   #define   UHIDEV_CLAIM_MULTIPLE_REPORTID  255
> > -   uint8_t  nreports;
> > +   u_intnreports;
> > uint8_t *claimed;
> >   };
> > 
> Hello Anton,
> 
> I made a quick test and nreports is now set with 256 but I still get the
> page fault.
> 
> I'll check the details ASAP.

Do you have a backtrace?



Re: upd(4) page fault since 7.0

2021-10-24 Thread Anton Lindqvist
On Sun, Oct 24, 2021 at 03:03:01PM +0200, Damien Couderc wrote:
> Hi,
> I got a page fault with upd(4) since 7.0.
> 
> The problem began with the last revision of upd.c (1.30):
> 
> ===
> RCS file: /cvs/src/sys/dev/usb/upd.c,v
> retrieving revision 1.29
> retrieving revision 1.30
> diff -u -r1.29 -r1.30
> --- src/sys/dev/usb/upd.c 2021/03/08 14:35:57 1.29
> +++ src/sys/dev/usb/upd.c 2021/08/06 17:46:45 1.30
> @@ -1,4 +1,4 @@
> -/*   $OpenBSD: upd.c,v 1.29 2021/03/08 14:35:57 jcs Exp $ */
> +/*   $OpenBSD: upd.c,v 1.30 2021/08/06 17:46:45 abieber Exp $ */
> 
>  /*
>   * Copyright (c) 2015 David Higgs 
> @@ -167,7 +167,7 @@
>   if (upd_lookup_usage_entry(desc, size,
>   upd_usage_roots + i, )) {
>   ret = UMATCH_VENDOR_PRODUCT;
> - break;
> + uha->claimed[item.report_ID] = 1;
>   }
> 
>   return (ret);
> 
> ===
> 
> The uha.claimed array is allocated using uha.nreports as its size while
> upd_match() is looping through the number of items of upd_usage_roots.
> 
> In my case uha.nreports is equal to zero so uha.claimed is null, hence
> setting uha->claimed[n] is failing.
> 
> As I'm not familiar with the HID code I did not yet understood the
> relation between upd_usage_roots and the claimed array but as we're
> talking about UPS attached computers I though the issue would sensible
> enough to make a quick reporting.
> 
> You'll find a dmesg with options UPD_DEBUG and UHIDEV_DEBUG set and the
> following patch applied to circumvent the page fault and provide some debug:

Could you try the following diff, looks like an unsigned wrap around.

Index: dev/usb/uhidev.h
===
RCS file: /cvs/src/sys/dev/usb/uhidev.h,v
retrieving revision 1.32
diff -u -p -r1.32 uhidev.h
--- dev/usb/uhidev.h12 Sep 2021 06:58:08 -  1.32
+++ dev/usb/uhidev.h24 Oct 2021 19:44:52 -
@@ -82,7 +82,7 @@ struct uhidev_attach_arg {
struct uhidev_softc *parent;
uint8_t  reportid;
 #defineUHIDEV_CLAIM_MULTIPLE_REPORTID  255
-   uint8_t  nreports;
+   u_intnreports;
uint8_t *claimed;
 };
 



ucc: ignore get encoding requests

2021-10-19 Thread Anton Lindqvist
Hi,
landry@ reported that he ended up with the wrong encoding in X11 while
having a ucc keyboard attached and /etc/kbdtype being present. The
advertised encoding of a wsmux is a bit fragile as the last attached
device will dictate it. If this happens to be a ucc keyboard, KB_US will
always be the advertised encoding as its encoding is immutable and
/etc/kbdtype is ignored.

Instead, do not advertise the encoding for ucc devices when the parent
mux queries its attached devices. However, asking the device directly
(i.e. bypassing the mux) still returns the encoding as wsconsctl(8)
would otherwise report an error.

Comments? OK?

Index: dev/wscons/wskbd.c
===
RCS file: /cvs/src/sys/dev/wscons/wskbd.c,v
retrieving revision 1.108
diff -u -p -r1.108 wskbd.c
--- dev/wscons/wskbd.c  20 Sep 2021 17:32:39 -  1.108
+++ dev/wscons/wskbd.c  20 Oct 2021 05:31:56 -
@@ -205,6 +205,8 @@ int wskbd_detach(struct device *, int);
 intwskbd_activate(struct device *, int);
 
 intwskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc 
*);
+intwskbd_displayioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
+struct proc *, int);
 
 void   update_leds(struct wskbd_internal *);
 void   update_modifier(struct wskbd_internal *, u_int, int, int);
@@ -217,7 +219,7 @@ voidchange_displayparam(struct wskbd_so
 #endif
 
 intwskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
-   struct proc *);
+struct proc *, int);
 void   wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value);
 
 #if NWSMUX > 0
@@ -925,7 +927,14 @@ wskbdread(dev_t dev, struct uio *uio, in
 int
 wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 {
-   return (wskbd_do_ioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, 
flag,p));
+   struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
+   int error;
+
+   sc->sc_refcnt++;
+   error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p, 0);
+   if (--sc->sc_refcnt < 0)
+   wakeup(sc);
+   return (error);
 }
 
 /* A wrapper around the ioctl() workhorse to make reference counting easy. */
@@ -937,7 +946,7 @@ wskbd_do_ioctl(struct device *dv, u_long
int error;
 
sc->sc_refcnt++;
-   error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p);
+   error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p, 1);
if (--sc->sc_refcnt < 0)
wakeup(sc);
return (error);
@@ -945,7 +954,7 @@ wskbd_do_ioctl(struct device *dv, u_long
 
 int
 wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
- struct proc *p)
+struct proc *p, int evsrc)
 {
struct wseventvar *evar;
int error;
@@ -983,7 +992,7 @@ wskbd_do_ioctl_sc(struct wskbd_softc *sc
 * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
 * if it didn't recognize the request.
 */
-   error = wskbd_displayioctl(>sc_base.me_dv, cmd, data, flag, p);
+   error = wskbd_displayioctl_sc(sc, cmd, data, flag, p, evsrc);
return (error != -1 ? error : ENOTTY);
 }
 
@@ -992,10 +1001,18 @@ wskbd_do_ioctl_sc(struct wskbd_softc *sc
  * Some of these have no real effect in raw mode, however.
  */
 int
-wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag,
+wskbd_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
 struct proc *p)
 {
-   struct wskbd_softc *sc = (struct wskbd_softc *)dev;
+   struct wskbd_softc *sc = (struct wskbd_softc *)dv;
+
+   return (wskbd_displayioctl_sc(sc, cmd, data, flag, p, 1));
+}
+
+int
+wskbd_displayioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data,
+int flag, struct proc *p, int evsrc)
+{
struct wskbd_bell_data *ubdp, *kbdp;
struct wskbd_keyrepeat_data *ukdp, *kkdp;
struct wskbd_map_data *umdp;
@@ -1134,6 +1151,9 @@ getkeyrepeat:
return(error);
 
case WSKBDIO_GETENCODING:
+   /* Do not advertise encoding to the parent mux. */
+   if (evsrc && (sc->id->t_keymap.layout & KB_NOENCODING))
+   return (ENOTTY);
*((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT;
return(0);
 



uhid(4): manual tweaks

2021-09-14 Thread Anton Lindqvist
Hi,
Improvements to the uhid(4) manual:

* Include the relevant header in the synopsis
* Document all supported ioctl commands
* Emphasis that a pointer is required to all ioctl commands
* Make the write(2) semantics a bit clearer
* Add files section
* Document errors

Comments? OK?

Index: uhid.4
===
RCS file: /cvs/src/share/man/man4/uhid.4,v
retrieving revision 1.19
diff -u -p -r1.19 uhid.4
--- uhid.4  30 Dec 2020 12:49:58 -  1.19
+++ uhid.4  14 Sep 2021 17:07:21 -
@@ -36,6 +36,8 @@
 .Nd USB generic HID support
 .Sh SYNOPSIS
 .Cd "uhid* at uhidev?"
+.Pp
+.In dev/usb/usb.h
 .Sh DESCRIPTION
 The
 .Nm
@@ -46,9 +48,11 @@ The device handles the following
 .Xr ioctl 2
 calls:
 .Bl -tag -width indent
-.It Dv USB_GET_REPORT_ID Fa int
+.It Dv USB_GET_DEVICEINFO Fa struct usb_device_info *devinfo
+Get summarized information about the device.
+.It Dv USB_GET_REPORT_ID Fa int *repid
 Get the report identifier used by this HID report.
-.It Dv USB_GET_REPORT_DESC Fa "struct usb_ctl_report_desc"
+.It Dv USB_GET_REPORT_DESC Fa struct usb_ctl_report_desc *repdesc
 Get the HID report descriptor.
 Using this descriptor the exact layout and meaning of data to/from
 the device can be found.
@@ -59,25 +63,24 @@ struct usb_ctl_report_desc {
 u_char  ucrd_data[1024];   /* filled data size will vary */
 };
 .Ed
-.It Dv USB_GET_REPORT Fa "struct usb_ctl_report"
+.It Dv USB_GET_REPORT Fa struct usb_ctl_report *rep
 Get a report from the device without waiting for data on
 the interrupt pipe.
 The
-.Fa report
+.Fa ucr_report
 field indicates which report is requested.
 It should be
 .Dv UHID_INPUT_REPORT ,
 .Dv UHID_OUTPUT_REPORT ,
 or
 .Dv UHID_FEATURE_REPORT .
-This call may fail if the device does not support this feature.
 .Bd -literal
 struct usb_ctl_report {
int ucr_report;
-   u_char  ucr_data[1024]; /* used data size will vary */
+   u_char  ucr_data[1024]; /* filled data size will vary */
 };
 .Ed
-.It Dv USB_SET_REPORT Fa "struct usb_ctl_report"
+.It Dv USB_SET_REPORT Fa struct usb_ctl_report *rep
 Set a report in the device.
 The
 .Dv report
@@ -87,9 +90,15 @@ It should be
 .Dv UHID_OUTPUT_REPORT ,
 or
 .Dv UHID_FEATURE_REPORT .
-This call may fail if the device does not support this feature.
 .El
 .Pp
+The generic ioctls
+.Dv FIONBIO
+and
+.Dv FIOASYNC
+are supported by
+.Nm .
+.Pp
 Use
 .Xr read 2
 to get data from the device.
@@ -98,8 +107,66 @@ Data should be read in chunks of the siz
 Use
 .Xr write 2
 to send data to the device.
+Equivalent to issuing an
+.Xr ioctl 2
+.Dv USB_SET_REPORT
+request with the report set to
+.Dv UHID_OUTPUT_REPORT .
 Data should be written in chunks of the size prescribed by the report
 descriptor.
+.Sh FILES
+.Bl -tag -width /dev/tun* -compact
+.It Pa /dev/uhid*
+.El
+.Sh ERRORS
+If
+.Xr ioctl 2
+fails,
+.Xr errno 2
+is set to one of the following:
+.Bl -tag -width Er
+.It Bq Er EIO
+The device could not fulfill a
+.Dv USB_GET_REPORT
+or
+.Dv USB_SET_REPORT
+request.
+.It Bq Er EINVAL
+The report specified by the
+.Fa ucr_report
+field in a
+.Dv USB_GET_REPORT
+or
+.Dv USB_SET_REPORT
+request was invalid.
+.It Bq Er ENOTTY
+Unrecognized command.
+.El
+.Pp
+If
+.Xr read 2
+fails,
+.Xr errno 2
+is set to one of the following:
+.Bl -tag -width Er
+.It Bq Er EIO
+The device has already been detached.
+.It Bq Er EWOULDBLOCK
+Non-blocking I/O was selected and no data were available.
+.El
+.Pp
+If
+.Xr write 2
+fails,
+.Xr errno 2
+is set to one of the following:
+.Bl -tag -width Er
+.It Bq Er EIO
+The device has already been detached or the same device does not have a
+corresponding output report.
+.It Bq Er EMSGSIZE
+The size of the supplied data exceeds the size of the output report.
+.El
 .Sh SEE ALSO
 .Xr usbhidctl 1 ,
 .Xr usbhid 3 ,



uhid(4): unknown ioctl command

2021-09-14 Thread Anton Lindqvist
Hi,
Change the errno to ENOTTY when encountering an unknown ioctl command as
opposed of using EINVAL which is ambiguous in this context.

Comments? OK?

Index: dev/usb/uhid.c
===
RCS file: /cvs/src/sys/dev/usb/uhid.c,v
retrieving revision 1.86
diff -u -p -r1.86 uhid.c
--- dev/usb/uhid.c  12 Sep 2021 06:58:08 -  1.86
+++ dev/usb/uhid.c  14 Sep 2021 16:49:33 -
@@ -392,7 +392,7 @@ uhid_do_ioctl(struct uhid_softc *sc, u_l
default:
rc = uhidev_ioctl(>sc_hdev, cmd, addr, flag, p);
if (rc == -1)
-   rc = EINVAL;
+   rc = ENOTTY;
return rc;
}
return (0);



Re: FIDO/U2F not working with latest snapshot

2021-09-12 Thread Anton Lindqvist
On Sun, Sep 12, 2021 at 12:53:30PM -0400, Mitchell Riedstra wrote:
> 
> > I have reverted the commit by now. Could you please send me the dmesg
> > and ssh-agent FIDO_DEBUG=1 output with and without this commit
> > applied.
> > 
> 
> Sure! See attached.

Thanks, the diff below should hopefully work as it corrects a regression
introduced in uhidev_attach(). However, I'm not still convinced that
this is a good idea.

Index: dev/usb/ucc.c
===
RCS file: /cvs/src/sys/dev/usb/ucc.c,v
retrieving revision 1.26
diff -u -p -r1.26 ucc.c
--- dev/usb/ucc.c   12 Sep 2021 06:58:08 -  1.26
+++ dev/usb/ucc.c   13 Sep 2021 05:09:13 -
@@ -633,9 +633,9 @@ ucc_match(struct device *parent, void *m
void *desc;
int size;
 
-   uhidev_get_report_desc(uha->parent, , );
-   if (hid_report_size(desc, size, hid_input, uha->reportid) == 0)
+   if (uha->isize == 0)
return UMATCH_NONE;
+   uhidev_get_report_desc(uha->parent, , );
if (!ucc_hid_match(desc, size, uha->reportid))
return UMATCH_NONE;
 
@@ -648,7 +648,7 @@ ucc_attach(struct device *parent, struct
struct ucc_softc *sc = (struct ucc_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
void *desc;
-   int error, repid, size;
+   int error, size;
 
sc->sc_mode = WSKBD_TRANSLATED;
sc->sc_last_translate = -1;
@@ -659,10 +659,9 @@ ucc_attach(struct device *parent, struct
sc->sc_hdev.sc_report_id = uha->reportid;
 
uhidev_get_report_desc(uha->parent, , );
-   repid = uha->reportid;
-   sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
-   sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
-   sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+   sc->sc_hdev.sc_isize = uha->isize;
+   sc->sc_hdev.sc_osize = uha->osize;
+   sc->sc_hdev.sc_fsize = uha->fsize;
 
error = ucc_hid_parse(sc, desc, size);
if (error) {
Index: dev/usb/ugold.c
===
RCS file: /cvs/src/sys/dev/usb/ugold.c,v
retrieving revision 1.19
diff -u -p -r1.19 ugold.c
--- dev/usb/ugold.c 12 Sep 2021 06:58:08 -  1.19
+++ dev/usb/ugold.c 13 Sep 2021 05:09:14 -
@@ -139,7 +139,7 @@ ugold_attach(struct device *parent, stru
 {
struct ugold_softc *sc = (struct ugold_softc *)self;
struct uhidev_attach_arg *uha = aux;
-   int size, repid;
+   int size;
void *desc;
 
sc->sc_udev = uha->parent->sc_udev;
@@ -159,10 +159,9 @@ ugold_attach(struct device *parent, stru
}
 
uhidev_get_report_desc(uha->parent, , );
-   repid = uha->reportid;
-   sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
-   sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
-   sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+   sc->sc_hdev.sc_isize = uha->isize;
+   sc->sc_hdev.sc_osize = uha->osize;
+   sc->sc_hdev.sc_fsize = uha->fsize;
 
if (uhidev_open(>sc_hdev)) {
printf(", unable to open interrupt pipe\n");
Index: dev/usb/uhid.c
===
RCS file: /cvs/src/sys/dev/usb/uhid.c,v
retrieving revision 1.86
diff -u -p -r1.86 uhid.c
--- dev/usb/uhid.c  12 Sep 2021 06:58:08 -  1.86
+++ dev/usb/uhid.c  13 Sep 2021 05:09:14 -
@@ -126,19 +126,15 @@ uhid_attach(struct device *parent, struc
 {
struct uhid_softc *sc = (struct uhid_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
-   int size, repid;
-   void *desc;
 
sc->sc_hdev.sc_intr = uhid_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_udev = uha->uaa->device;
sc->sc_hdev.sc_report_id = uha->reportid;
 
-   uhidev_get_report_desc(uha->parent, , );
-   repid = uha->reportid;
-   sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
-   sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
-   sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+   sc->sc_hdev.sc_isize = uha->isize;
+   sc->sc_hdev.sc_osize = uha->osize;
+   sc->sc_hdev.sc_fsize = uha->fsize;
 
printf(": input=%d, output=%d, feature=%d\n",
sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize);
Index: dev/usb/uhidev.c
===
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.95
diff -u -p -r1.95 uhidev.c
--- dev/usb/uhidev.c12 Sep 2021 06:58:08 -  1.95
+++ dev/usb/uhidev.c13 Sep 2021 05:09:15 -
@@ -252,6 +252,7 @@ uhidev_attach(struct device *parent, str
uha.reportid = 

ucc: ignore set encoding requests

2021-09-12 Thread Anton Lindqvist
Hi,
landry@ reported that kbd spits out the following error while booting
with a ucc keyboard attached and /etc/kbdtype being present:

kbd: unsupported encoding uk on /dev/wskbd2

Changing the encoding of a ucc keyboard doesn't make sense as only one
encoding is supported. Instead, silently ignore such requests. I ended
up repurposing KB_MACHDEP as is became unused back in 2008. Note that
kbd and wsconsctl must be recompiled as they rely on KDBVAR_TAB.

Comments? OK?

Index: dev/usb/ucc.c
===
RCS file: /cvs/src/sys/dev/usb/ucc.c,v
retrieving revision 1.26
diff -u -p -r1.26 ucc.c
--- dev/usb/ucc.c   12 Sep 2021 06:58:08 -  1.26
+++ dev/usb/ucc.c   12 Sep 2021 15:22:03 -
@@ -788,7 +788,7 @@ ucc_attach_wskbd(struct ucc_softc *sc)
sc->sc_keydesc[0].map_size = sc->sc_maplen;
sc->sc_keydesc[0].map = sc->sc_map;
sc->sc_keymap.keydesc = sc->sc_keydesc;
-   sc->sc_keymap.layout = KB_US;
+   sc->sc_keymap.layout = KB_US | KB_NOENCODING;
sc->sc_wskbddev = config_found(>sc_hdev.sc_dev, , wskbddevprint);
 }
 
Index: dev/wscons/wskbd.c
===
RCS file: /cvs/src/sys/dev/wscons/wskbd.c,v
retrieving revision 1.107
diff -u -p -r1.107 wskbd.c
--- dev/wscons/wskbd.c  2 Nov 2020 19:45:18 -   1.107
+++ dev/wscons/wskbd.c  12 Sep 2021 15:22:04 -
@@ -1146,6 +1146,8 @@ getkeyrepeat:
/* map variants make no sense */
if (KB_VARIANT(enc) & ~KB_HANDLEDBYWSKBD)
return (EINVAL);
+   } else if (sc->id->t_keymap.layout & KB_NOENCODING) {
+   return (0);
} else {
error = wskbd_load_keymap(>id->t_keymap, enc,
>sc_map, >sc_maplen);
Index: dev/wscons/wsksymdef.h
===
RCS file: /cvs/src/sys/dev/wscons/wsksymdef.h,v
retrieving revision 1.38
diff -u -p -r1.38 wsksymdef.h
--- dev/wscons/wsksymdef.h  11 May 2019 14:19:16 -  1.38
+++ dev/wscons/wsksymdef.h  12 Sep 2021 15:22:04 -
@@ -744,7 +744,7 @@
 #define KB_DVORAK  0x0010 /* Dvorak layout */
 #define KB_METAESC 0x0020 /* generate ESC prefix on ALT-key */
 #define KB_IOPENER 0x0040 /* f1-f12 -> ESC,f1-f11 */
-#define KB_MACHDEP 0x0080 /* machine dependent */
+#define KB_NOENCODING  0x0080 /* no encodings available */
 #define KB_APPLE   0x0001 /* Apple specific layout */
 #define KB_COLEMAK 0x0200 /* Colemak layout */
 #define KB_DEFAULT 0x8000 /* (attach-only) default layout */
@@ -788,7 +788,7 @@
{ KB_DVORAK,"dvorak" }, \
{ KB_METAESC,   "metaesc" }, \
{ KB_IOPENER,   "iopener" }, \
-   { KB_MACHDEP,   "machdep" }, \
+   { KB_NOENCODING, "noencoding" }, \
{ KB_APPLE, "apple" }, \
{ KB_COLEMAK,   "colemak" }
 
Index: dev/wscons/wsksymvar.h
===
RCS file: /cvs/src/sys/dev/wscons/wsksymvar.h,v
retrieving revision 1.8
diff -u -p -r1.8 wsksymvar.h
--- dev/wscons/wsksymvar.h  26 Jan 2014 17:48:08 -  1.8
+++ dev/wscons/wsksymvar.h  12 Sep 2021 15:22:04 -
@@ -60,7 +60,7 @@ struct wskbd_mapdata {
 };
 
 /* layout variant bits ignored by mapping code */
-#define KB_HANDLEDBYWSKBD  (KB_METAESC | KB_DEFAULT)
+#define KB_HANDLEDBYWSKBD  (KB_METAESC | KB_DEFAULT | KB_NOENCODING)
 
 /*
  * Utility functions.



Re: FIDO/U2F not working with latest snapshot

2021-09-12 Thread Anton Lindqvist
On Sat, Sep 11, 2021 at 07:56:47PM -0400, Mitchell Riedstra wrote:
> I see the same issue, it seems to be impacting everything with libfido,
> ( ed25519-sk and ecdsa-sk SSH keys as well ) Reverting that commit also
> fixes the issue for me.
> 
> I don't see anything obvious in dmesg, running ssh-agent with
> FIDO_DEBUG=1 yields a small bit more information to go on:
> 
> debug1: start_helper: starting /usr/libexec/ssh-sk-helper
> debug1: process_sign: ready to sign with key ED25519-SK, provider
> internal: msg len 186, compat 0x0
> debug1: sshsk_sign: provider "internal", key ED25519-SK, flags 0x21
> fido_hid_manifest: /dev/fido/0: vendor = "OpenBSD", product = "fido(4)"
> debug1: sk_probe: 1 device(s) detected
> debug1: sk_probe: selecting sk by cred
> fido_hid_open: inlen = 64 outlen = 64
> terrible_ping_kludge: send ping 0
> fido_hid_write: write: Message too long
> fido_dev_open_tx: dev->io.open
> debug1: sk_open: fido_dev_open /dev/fido/0 failed: FIDO_ERR_INTERNAL

I have reverted the commit by now. Could you please send me the dmesg
and ssh-agent FIDO_DEBUG=1 output with and without this commit applied.



uhidev: report sizes

2021-09-08 Thread Anton Lindqvist
Hi,
Instead of letting uhidev drivers get the report sizes, do it once in
uhidev and pass the same sizes as part of the attach arguments. Makes
the uhidev drivers a bit less repetitive. Note that each call to
uhidev_get_report_size() requires one malloc() and a full traversal of
the HID report. Not that this change will cause any noticeable
difference in terms of time but we can at least avoid doing the same
operation over and over.

It might look tempting to let uhidev assign the sizes after a driver has
attached, removing the need to repeat this logic in each driver. This
does however not work since the input size (sc_isize) must be known
while calling uhidev_open() in order to open the interrupt pipe; and
uhidev_open() is called from several attach routines.

Note that this change only works and applies to when attaching to a
single report ID.

While here, get rid of the unused repsize array.

Comments? OK?

Index: dev/usb/ucc.c
===
RCS file: /cvs/src/sys/dev/usb/ucc.c,v
retrieving revision 1.24
diff -u -p -r1.24 ucc.c
--- dev/usb/ucc.c   2 Sep 2021 15:15:12 -   1.24
+++ dev/usb/ucc.c   9 Sep 2021 05:26:35 -
@@ -633,9 +633,9 @@ ucc_match(struct device *parent, void *m
void *desc;
int size;
 
-   uhidev_get_report_desc(uha->parent, , );
-   if (hid_report_size(desc, size, hid_input, uha->reportid) == 0)
+   if (uha->isize == 0)
return UMATCH_NONE;
+   uhidev_get_report_desc(uha->parent, , );
if (!ucc_hid_match(desc, size, uha->reportid))
return UMATCH_NONE;
 
@@ -648,7 +648,7 @@ ucc_attach(struct device *parent, struct
struct ucc_softc *sc = (struct ucc_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
void *desc;
-   int error, repid, size;
+   int error, size;
 
sc->sc_mode = WSKBD_TRANSLATED;
sc->sc_last_translate = -1;
@@ -659,10 +659,9 @@ ucc_attach(struct device *parent, struct
sc->sc_hdev.sc_report_id = uha->reportid;
 
uhidev_get_report_desc(uha->parent, , );
-   repid = uha->reportid;
-   sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
-   sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
-   sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+   sc->sc_hdev.sc_isize = uha->isize;
+   sc->sc_hdev.sc_osize = uha->osize;
+   sc->sc_hdev.sc_fsize = uha->fsize;
 
error = ucc_hid_parse(sc, desc, size);
if (error) {
Index: dev/usb/ugold.c
===
RCS file: /cvs/src/sys/dev/usb/ugold.c,v
retrieving revision 1.17
diff -u -p -r1.17 ugold.c
--- dev/usb/ugold.c 5 Apr 2021 16:26:06 -   1.17
+++ dev/usb/ugold.c 9 Sep 2021 05:26:35 -
@@ -139,7 +139,7 @@ ugold_attach(struct device *parent, stru
 {
struct ugold_softc *sc = (struct ugold_softc *)self;
struct uhidev_attach_arg *uha = aux;
-   int size, repid;
+   int size;
void *desc;
 
sc->sc_udev = uha->parent->sc_udev;
@@ -159,10 +159,9 @@ ugold_attach(struct device *parent, stru
}
 
uhidev_get_report_desc(uha->parent, , );
-   repid = uha->reportid;
-   sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
-   sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
-   sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+   sc->sc_hdev.sc_isize = uha->isize;
+   sc->sc_hdev.sc_osize = uha->osize;
+   sc->sc_hdev.sc_fsize = uha->fsize;
 
if (uhidev_open(>sc_hdev)) {
printf(", unable to open interrupt pipe\n");
Index: dev/usb/uhid.c
===
RCS file: /cvs/src/sys/dev/usb/uhid.c,v
retrieving revision 1.84
diff -u -p -r1.84 uhid.c
--- dev/usb/uhid.c  8 Mar 2021 14:35:57 -   1.84
+++ dev/usb/uhid.c  9 Sep 2021 05:26:35 -
@@ -126,7 +126,7 @@ uhid_attach(struct device *parent, struc
 {
struct uhid_softc *sc = (struct uhid_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
-   int size, repid;
+   int size;
void *desc;
 
sc->sc_hdev.sc_intr = uhid_intr;
@@ -135,10 +135,9 @@ uhid_attach(struct device *parent, struc
sc->sc_hdev.sc_report_id = uha->reportid;
 
uhidev_get_report_desc(uha->parent, , );
-   repid = uha->reportid;
-   sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
-   sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
-   sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+   sc->sc_hdev.sc_isize = uha->isize;
+   sc->sc_hdev.sc_osize = uha->osize;
+   sc->sc_hdev.sc_fsize = uha->fsize;
 
printf(": input=%d, 

Re: ucc(4): slice interrupt report

2021-08-26 Thread Anton Lindqvist
On Fri, Aug 27, 2021 at 07:05:06AM +0200, Anton Lindqvist wrote:
> Hi,
> An interrupt report contains the state of all items (Input, Output and
> Feature) from the corresponding descriptor report for a given report ID.
> The ordering of the items is identical in both the descriptor and
> interrupt report. As the interrupt report can cover more than Consumer
> Control related key presses, ucc must be more careful while examining
> the interrupt report in order to not confuse other items as key presses.
> 
> While parsing the descriptor report, take note of the bits that
> represents Consumer Control key presses and use it to slice the
> interrupt report.
> 
> Testing would be much appreciated. Note that UCC_DEBUG is intentionally
> enabled in the diff below. Please send me your dmesg after pressing at
> least one recognized key.

Updated diff fixing handling constant padding input.

Index: dev/usb/ucc.c
===
RCS file: /cvs/src/sys/dev/usb/ucc.c,v
retrieving revision 1.13
diff -u -p -r1.13 ucc.c
--- dev/usb/ucc.c   26 Aug 2021 10:32:35 -  1.13
+++ dev/usb/ucc.c   27 Aug 2021 05:34:34 -
@@ -31,7 +31,7 @@
 #include 
 #include 
 
-/* #define UCC_DEBUG */
+#define UCC_DEBUG
 #ifdef UCC_DEBUG
 #define DPRINTF(x...)  do { if (ucc_debug) printf(x); } while (0)
 void   ucc_dump(const char *, u_char *, u_int);
@@ -58,6 +58,17 @@ struct ucc_softc {
int   sc_isarray;
int   sc_mode;
 
+   /*
+* Slice of the interrupt buffer which represents a pressed key.
+* See section 8 (Report Protocol) of the HID specification v1.11.
+*/
+   struct {
+   uint8_t *i_buf;
+   uint32_t i_bufsiz;
+   uint32_t i_off; /* offset in bits */
+   uint32_t i_len; /* length in bits */
+   } sc_input;
+
/* Last pressed key. */
union {
int sc_last_translate;
@@ -92,6 +103,7 @@ int  ucc_add_key(struct ucc_softc *, int3
 intucc_bit_to_sym(struct ucc_softc *, u_int, const struct ucc_keysym **);
 intucc_usage_to_sym(int32_t, const struct ucc_keysym **);
 intucc_bits_to_usage(u_char *, u_int, int32_t *);
+intucc_intr_slice(struct ucc_softc *, u_char *, u_char *, int *);
 void   ucc_input(struct ucc_softc *, u_int, int);
 void   ucc_rawinput(struct ucc_softc *, u_char, int);
 intucc_setbits(u_char *, int, u_int *);
@@ -194,6 +206,7 @@ ucc_detach(struct device *self, int flag
if (sc->sc_wskbddev != NULL)
error = config_detach(sc->sc_wskbddev, flags);
uhidev_close(>sc_hdev);
+   free(sc->sc_input.i_buf, M_USBDEV, sc->sc_input.i_bufsiz);
free(sc->sc_map, M_USBDEV, sc->sc_mapsiz * sizeof(*sc->sc_map));
free(sc->sc_raw, M_USBDEV, sc->sc_rawsiz * sizeof(*sc->sc_raw));
return error;
@@ -204,13 +217,30 @@ ucc_intr(struct uhidev *addr, void *data
 {
struct ucc_softc *sc = (struct ucc_softc *)addr;
const struct ucc_keysym *us;
+   u_char *buf = sc->sc_input.i_buf;
int raw = sc->sc_mode == WSKBD_RAW;
+   int error;
u_int bit = 0;
u_char c = 0;
 
ucc_dump(__func__, data, len);
 
-   if (ucc_setbits(data, len, )) {
+   if (len > sc->sc_input.i_bufsiz) {
+   DPRINTF("%s: too much data: len %d, bufsiz %d\n", __func__,
+   len, sc->sc_input.i_bufsiz);
+   return;
+   }
+
+   error = ucc_intr_slice(sc, data, buf, );
+   if (error) {
+   DPRINTF("%s: slice failure: error %d\n", __func__, error);
+   return;
+   }
+
+   /* Dump the buffer again after slicing. */
+   ucc_dump(__func__, buf, len);
+
+   if (ucc_setbits(buf, len, )) {
/* All zeroes, assume key up event. */
if (raw) {
if (sc->sc_last_raw != 0) {
@@ -227,7 +257,7 @@ ucc_intr(struct uhidev *addr, void *data
} else if (sc->sc_isarray) {
int32_t usage;
 
-   if (ucc_bits_to_usage(data, len, ) ||
+   if (ucc_bits_to_usage(buf, len, ) ||
ucc_usage_to_sym(usage, ))
goto unknown;
bit = us->us_usage;
@@ -338,10 +368,12 @@ ucc_ioctl(void *v, u_long cmd, caddr_t d
 int
 ucc_hid_parse(struct ucc_softc *sc, void *desc, int descsiz)
 {
+   enum { OFFSET, LENGTH } istate = OFFSET;
struct hid_item hi;
struct hid_data *hd;
-   int nsyms = nitems(ucc_keysyms);
int error = 0;
+   int nsyms = nitems(ucc_keysyms);
+   int repid = sc->sc_hdev.sc_report_id;
int isize;
 
/*
@@ -353,6 +385,10 @@ ucc_hid_parse(struct ucc_softc *sc, void
if (isize == 0)
return ENXIO;
 

ucc(4): slice interrupt report

2021-08-26 Thread Anton Lindqvist
Hi,
An interrupt report contains the state of all items (Input, Output and
Feature) from the corresponding descriptor report for a given report ID.
The ordering of the items is identical in both the descriptor and
interrupt report. As the interrupt report can cover more than Consumer
Control related key presses, ucc must be more careful while examining
the interrupt report in order to not confuse other items as key presses.

While parsing the descriptor report, take note of the bits that
represents Consumer Control key presses and use it to slice the
interrupt report.

Testing would be much appreciated. Note that UCC_DEBUG is intentionally
enabled in the diff below. Please send me your dmesg after pressing at
least one recognized key.

Index: dev/usb/ucc.c
===
RCS file: /cvs/src/sys/dev/usb/ucc.c,v
retrieving revision 1.13
diff -u -p -r1.13 ucc.c
--- dev/usb/ucc.c   26 Aug 2021 10:32:35 -  1.13
+++ dev/usb/ucc.c   27 Aug 2021 05:03:33 -
@@ -31,7 +31,7 @@
 #include 
 #include 
 
-/* #define UCC_DEBUG */
+#define UCC_DEBUG
 #ifdef UCC_DEBUG
 #define DPRINTF(x...)  do { if (ucc_debug) printf(x); } while (0)
 void   ucc_dump(const char *, u_char *, u_int);
@@ -58,6 +58,14 @@ struct ucc_softc {
int   sc_isarray;
int   sc_mode;
 
+   /* Slice of the interrupt buffer which represents a pressed key. */
+   struct {
+   uint8_t *i_buf;
+   uint32_t i_bufsiz;
+   uint32_t i_off; /* offset in bits */
+   uint32_t i_len; /* length in bits */
+   } sc_input;
+
/* Last pressed key. */
union {
int sc_last_translate;
@@ -92,6 +100,7 @@ int  ucc_add_key(struct ucc_softc *, int3
 intucc_bit_to_sym(struct ucc_softc *, u_int, const struct ucc_keysym **);
 intucc_usage_to_sym(int32_t, const struct ucc_keysym **);
 intucc_bits_to_usage(u_char *, u_int, int32_t *);
+intucc_intr_slice(struct ucc_softc *, u_char *, u_char *, int *);
 void   ucc_input(struct ucc_softc *, u_int, int);
 void   ucc_rawinput(struct ucc_softc *, u_char, int);
 intucc_setbits(u_char *, int, u_int *);
@@ -194,6 +203,7 @@ ucc_detach(struct device *self, int flag
if (sc->sc_wskbddev != NULL)
error = config_detach(sc->sc_wskbddev, flags);
uhidev_close(>sc_hdev);
+   free(sc->sc_input.i_buf, M_USBDEV, sc->sc_input.i_bufsiz);
free(sc->sc_map, M_USBDEV, sc->sc_mapsiz * sizeof(*sc->sc_map));
free(sc->sc_raw, M_USBDEV, sc->sc_rawsiz * sizeof(*sc->sc_raw));
return error;
@@ -204,13 +214,30 @@ ucc_intr(struct uhidev *addr, void *data
 {
struct ucc_softc *sc = (struct ucc_softc *)addr;
const struct ucc_keysym *us;
+   u_char *buf = sc->sc_input.i_buf;
int raw = sc->sc_mode == WSKBD_RAW;
+   int error;
u_int bit = 0;
u_char c = 0;
 
ucc_dump(__func__, data, len);
 
-   if (ucc_setbits(data, len, )) {
+   if (len > sc->sc_input.i_bufsiz) {
+   DPRINTF("%s: too much data: len %d, bufsiz %d\n", __func__,
+   len, sc->sc_input.i_bufsiz);
+   return;
+   }
+
+   error = ucc_intr_slice(sc, data, buf, );
+   if (error) {
+   DPRINTF("%s: slice failure: error %d\n", __func__, error);
+   return;
+   }
+
+   /* Dump the buffer again after slicing. */
+   ucc_dump(__func__, buf, len);
+
+   if (ucc_setbits(buf, len, )) {
/* All zeroes, assume key up event. */
if (raw) {
if (sc->sc_last_raw != 0) {
@@ -227,7 +254,7 @@ ucc_intr(struct uhidev *addr, void *data
} else if (sc->sc_isarray) {
int32_t usage;
 
-   if (ucc_bits_to_usage(data, len, ) ||
+   if (ucc_bits_to_usage(buf, len, ) ||
ucc_usage_to_sym(usage, ))
goto unknown;
bit = us->us_usage;
@@ -338,10 +365,12 @@ ucc_ioctl(void *v, u_long cmd, caddr_t d
 int
 ucc_hid_parse(struct ucc_softc *sc, void *desc, int descsiz)
 {
+   enum { OFFSET, LENGTH } istate = OFFSET;
struct hid_item hi;
struct hid_data *hd;
-   int nsyms = nitems(ucc_keysyms);
int error = 0;
+   int nsyms = nitems(ucc_keysyms);
+   int repid = sc->sc_hdev.sc_report_id;
int isize;
 
/*
@@ -353,6 +382,10 @@ ucc_hid_parse(struct ucc_softc *sc, void
if (isize == 0)
return ENXIO;
 
+   /* Allocate buffer used to slice interrupt data. */
+   sc->sc_input.i_bufsiz = sc->sc_hdev.sc_isize;
+   sc->sc_input.i_buf = malloc(sc->sc_input.i_bufsiz, M_USBDEV, M_WAITOK);
+
/*
 * Create mapping between each input bit and the corresponding usage,
 * used in translating mode. Two entries are needed per bit in order
@@ 

ucc(4): enumerate all usages

2021-08-25 Thread Anton Lindqvist
Hi,
As the Consumer Control usages are well defined by the HID Usage Tables
specification ucc might as well enumerate all of them. Finding an
appropriate scan code recognized by X11 for each usage is more tricky.
I've added a few more but the majority are still unmapped. Linux has
defined a couple of more usages covered by the evdev key codes
($xenocara/dist/xkeyboard-config/keycodes/evdev) but those symbols are
not picked up in an vanilla X11 configuration on OpenBSD, according to
setxkbmap(1).

This should at least lower the barrier for adding scan codes for wanted
keys.

Note that the strings are discarded unless UCC_DEBUG is enabled.

Comments? OK?

Index: dev/usb/ucc.c
===
RCS file: /cvs/src/sys/dev/usb/ucc.c,v
retrieving revision 1.11
diff -u -p -r1.11 ucc.c
--- dev/usb/ucc.c   25 Aug 2021 05:48:50 -  1.11
+++ dev/usb/ucc.c   25 Aug 2021 05:56:13 -
@@ -69,7 +69,9 @@ struct ucc_softc {
 };
 
 struct ucc_keysym {
+#ifdef UCC_DEBUG
const char  *us_name;
+#endif
int32_t  us_usage;
keysym_t us_key;
u_char   us_raw;
@@ -108,26 +110,493 @@ const struct cfattach ucc_ca = {
 };
 
 /*
- * Mapping of HID consumer control usages to key symbols.
- * The raw scan codes are taken from X11, see the media_common symbols in
- * dist/xkeyboard-config/symbols/inet.
+ * Mapping of HID Consumer Control usages to key symbols based on the HID Usage
+ * Tables 1.21 specification. The same usages can also be found at
+ * /usr/share/misc/usb_hid_usages.
+ * The raw scan codes are taken from X11, see the media_nav_acpi_common symbols
+ * in dist/xkeyboard-config/symbols/inet.
  * Then use dist/xkeyboard-config/keycodes/xfree86 to resolve keys to the
  * corresponding raw scan code.
  */
 static const struct ucc_keysym ucc_keysyms[] = {
 #ifdef UCC_DEBUG
-#define U(x)   #x, x
+#define Y(usage, name, key, raw)   { name, usage, key, raw },
 #else
-#define U(x)   NULL, x
+#define Y(usage, name, key, raw)   { usage, key, raw },
 #endif
-   { U(HUC_MUTE),  KS_AudioMute,   0 },
-   { U(HUC_VOL_INC),   KS_AudioRaise,  0 },
-   { U(HUC_VOL_DEC),   KS_AudioLower,  0 },
-   { U(HUC_TRACK_NEXT),0,  153 /* I19 = XF86AudioNext */ },
-   { U(HUC_TRACK_PREV),0,  144 /* I10 = XF86AudioPrev */ },
-   { U(HUC_STOP),  0,  164 /* I24 = XF86AudioStop */ },
-   { U(HUC_PLAY_PAUSE),0,  162 /* I22 = XF86AudioPlay, 
XF86AudioPause */ },
-#undef U
+#define N(usage, name, key, raw)
+   /* 0x Unassigned */
+   N(0x0001,   "Consumer Control", 0,  
0)
+   N(0x0002,   "Numeric Key Pad",  0,  
0)
+   N(0x0003,   "Programmable Buttons", 0,  
0)
+   N(0x0004,   "Microphone",   0,  
0)
+   N(0x0005,   "Headphone",0,  
0)
+   N(0x0006,   "Graphic Equalizer",0,  
0)
+   /* 0x0007-0x001F Reserved */
+   N(0x0020,   "+10",  0,  
0)
+   N(0x0021,   "+100", 0,  
0)
+   N(0x0022,   "AM/PM",0,  
0)
+   /* 0x0023-0x002F Reserved */
+   Y(0x0030,   "Power",0,  
222 /* I5E = XF86PowerOff */)
+   N(0x0031,   "Reset",0,  
0)
+   Y(0x0032,   "Sleep",0,  
150 /* I16 = XF86Sleep */)
+   N(0x0033,   "Sleep After",  0,  
0)
+   N(0x0034,   "Sleep Mode",   0,  
0)
+   N(0x0035,   "Illumination", 0,  
0)
+   N(0x0036,   "Function Buttons", 0,  
0)
+   /* 0x0037-0x003F Reserved */
+   N(0x0040,   "Menu", 0,  
0)
+   N(0x0041,   "Menu Pick",0,  
0)
+   N(0x0042,   "Menu Up",  0,  
0)
+   N(0x0043,   "Menu Down",0,  
0)
+   N(0x0044,   "Menu Left",0,  
0)
+   N(0x0045,   "Menu Right",   0,  
0)
+   N(0x0046,   "Menu Escape",  0,  
0)
+   N(0x0047,   "Menu Value Increase",

Re: ucc(4): consumer control keyboard device driver

2021-08-24 Thread Anton Lindqvist
Hi,

On Fri, Aug 20, 2021 at 10:48:28PM -0700, David Rinehart wrote:
> I use usbhidaction, a little differently:
> 
> - OBSD media server in office, connected to speakers
> 
> - Custom microservice on media server, to control volume
> 
> - When I am docked at startup (detected in .xsession), configure:
> 
>   - Set AUDIODEVICE to office media server for sndio
> 
>   - Use usbhidaction to send volume and mute commands to media
> center microservice
> 
> This setup works incredibly well - and I would never have considered it
> with other OSs.  I would have tried to rig a headphone jack and
> splitter or something.  Current config just uses the network.
> 
> Since I have other OBSD media servers around the house, I can easily
> change the address and send audio & control to other rooms.
> 
> Wondering if my custom config will still be possible with ucc...

I'm afraid it won't work with your setup. As I understand things, you're
reacting to certain buttons and relaying the associated action to your
media server using usbhidaction? I see two alternatives:

1. Disable ucc completely keeping your old setup intact.

2. Wondering if one could write a small X11 utility that listens for
   keyboard input and reacts to certian keys like XF86AudioMute. This
   requires some trivial tweak to ucc as it currently does not emit any
   scan codes for the volume related usages in raw mode.



Re: ucc(4): consumer control keyboard device driver

2021-08-19 Thread Anton Lindqvist
On Wed, Aug 18, 2021 at 12:01:53PM -0500, joshua stein wrote:
> On Wed, 18 Aug 2021 at 18:48:45 +0200, Martin Pieuchot wrote:
> > Regarding the introduction of a separate wskbd(4) this can be seen as an
> > intermediate step.  Having this logic in ukbd(4) implies revisiting the
> > way reportID are mapped to USB drivers, which is still a bit of a hack
> > when it comes to supporting multiple of them.  Having a simpler driver
> > like ucc(4) can help us figure out out to support more "special" keys
> > without having to deal with the HID logic at the same time.
> > 
> > It would be great if users of usbhidaction(1) could tell us if this
> > introduce any regression and/or if other keys could be supported.
> 
> I used usbhidaction for a Bluetooth audio device that supported 
> passing button presses through.
> 
> https://jcs.org/2020/11/18/openbsd_btaudio#responding-to-headphone-buttons
> 
> $ cat .usbhidaction.conf
> Consumer:Play/Pause 1
> ~/bin/music playpause
> 
> Due to the lack of an XF86Audio* keysym that is both "play/pause", 
> ucc can only map it to just XF86AudioPlay.  It's no big deal for me 
> to adapt though, and I'm happy to see a driver do all of this 
> automatically.
> 
> Though it would be nice to find a way to pass any unsupported 
> buttons through, even if they are just no-named keysyms that would 
> at least allow a program to bind/react to them.

I'm currently looking into what hid-input in Linux does while
encountering unknown keys.



Re: ucc(4): consumer control keyboard device driver

2021-08-17 Thread Anton Lindqvist
On Tue, Aug 17, 2021 at 10:08:35PM +0200, Paul de Weerd wrote:
> Hi Anton,
> 
> Thanks - I've applied your diff and built a kernel with it.  Full
> dmesg (both before and after) at the end of this mail, diff is:
> 
> -uhid2 at uhidev3 reportid 3: input=3, output=0, feature=0
> +ucc0 at uhidev3 reportid 3 keys 24, mappings 7
> +wskbd3 at ucc0 mux 1
> 
> -wskbd3 at ukbd2 mux 1
> -uhid3 at uhidev5 reportid 3: input=4, output=0, feature=0
> -uhid4 at uhidev5 reportid 4: input=1, output=0, feature=0
> -uhidpp0 at uhidev5 reportid 16
> +wskbd4 at ukbd2 mux 1
> +ucc1 at uhidev5 reportid 3 keys 0, mappings 0
> +uhid2 at uhidev5 reportid 4: input=1, output=0, feature=0
> +uhidpp0 at uhidev5 reportid 16
> 
> That is with this keyboard:
> 
> [weerd@pom] $ dmesg | grep Metadot
> uhidev2 at uhub3 port 4 configuration 1 interface 0 "Metadot - Das Keyboard 
> Das Keyboard" rev 2.00/1.00 addr 4
> uhidev3 at uhub3 port 4 configuration 1 interface 1 "Metadot - Das Keyboard 
> Das Keyboard" rev 2.00/1.00 addr 4
> [weerd@pom] $ usbdevs -v -a 04
> addr 04: 24f0:0140 Metadot - Das Keyboard, Das Keyboard
>  full speed, power 100 mA, config 1, rev 1.00
>  driver: uhidev2
>  driver: uhidev3
> 
> (there's a few more deltas that I'm leaving out due to an external
> AHCI controller not being detected).
> 
> Anyway, I see two ucc(4) devices - not sure why that is; assuming it's
> because the keyboard itself also shows up twice.  But at least the
> volume control works.  Playing an audio file with mpd and turning the
> big volume knob on my keyboard changes the volume (also indicated by
> sndioctl(1).  The 'mute' button doesn't do anything, but I may have to
> dig a bit more into how this works first.
> 
> I'll play around with this a bit more, but initial results look very
> promising - thanks for this new driver!

The second one is from your Logitech MX518 mouse. What would be helpful
is a raw dump of the USB HID report descriptor from both the mouse and
your keyboard. In order get the reports, one must boot a kernel without
ucc making the two devices attach as uhid as opposed of being matched by
ucc. Then run the following command once per device, the uhid numbers
are taken from your dmesg before applying the ucc diff:

# usbhidctl -f /dev/uhid2 -R >keyboard
# usbhidctl -f /dev/uhid3 -R >mouse

As for the mute button, could you enable UCC_DEBUG in dev/usb/ucc.c,
compile and install the new kernel, make sure to press the mute button
and then send me the dmesg output please.



ucc(4): consumer control keyboard device driver

2021-08-17 Thread Anton Lindqvist
Hi,
Here's a new driver for USB HID Consumer Control keyboards. Such
keyboard is a pseudo device which is used to expose audio and
application launch keys. My prime motivation is to get the volume mute,
increment and decrement keys to just work on my keyboard without the
need to use usbhidaction(1).

ucc(4) attaches a wskbd(4) keyboard "on top" making it appear like an
ordinary keyboard, which also makes it possible to inject key
press/release input. It supports both translating and raw mode making it
compatible with the ordinary console and X11.

My keyboard for instance exposes 42 keys in its input report. I only
care about the volume and audio related ones and therefore only added
mappings for those. Additional mappings should be trivial to add if
desired.

Testing would be much appreciated.

Comments? OK?

diff --git share/man/man4/Makefile share/man/man4/Makefile
index 6a0ecb20653..63b33660159 100644
--- share/man/man4/Makefile
+++ share/man/man4/Makefile
@@ -84,7 +84,7 @@ MAN=  aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 acrtc.4 \
tlphy.4 thmc.4 tpm.4 tpmr.4 tqphy.4 trm.4 trunk.4 tsl.4 tty.4 \
tun.4 tap.4 twe.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 \
+   ubsec.4 ucc.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 uhidpp.4 \
uipaq.4 ujoy.4 uk.4 ukbd.4 \
diff --git share/man/man4/ucc.4 share/man/man4/ucc.4
new file mode 100644
index 000..413c88aa6af
--- /dev/null
+++ share/man/man4/ucc.4
@@ -0,0 +1,45 @@
+.\"$OpenBSD$
+.\"
+.\" Copyright (c) 2021 Anton Lindqvist 
+.\"
+.\" 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 UCC 4
+.Os
+.Sh NAME
+.Nm ucc
+.Nd Consumer Control keyboards
+.Sh SYNOPSIS
+.Cd "ucc* at uhidev?"
+.Cd "wsbkd* at ucc? mux 1"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for Consumer Control pseudo keyboards, often used to
+expose audio and application launch keys.
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr uhidev 4 ,
+.Xr usb 4 ,
+.Xr wskbd 4
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 7.0 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Anton Lindqvist Aq Mt an...@openbsd.org .
diff --git share/man/man4/uhidev.4 share/man/man4/uhidev.4
index 02252789a3f..d398c564bd5 100644
--- share/man/man4/uhidev.4
+++ share/man/man4/uhidev.4
@@ -37,6 +37,7 @@
 .Sh SYNOPSIS
 .Cd "uhidev*  at uhub?"
 .Cd "fido*at uhidev?"
+.Cd "ucc* at uhidev?"
 .Cd "ucycom*  at uhidev?"
 .Cd "ugold*   at uhidev?"
 .Cd "uhid*at uhidev?"
@@ -72,6 +73,7 @@ only dispatches data to them based on the report id.
 .Sh SEE ALSO
 .Xr fido 4 ,
 .Xr intro 4 ,
+.Xr ucc 4 ,
 .Xr ucycom 4 ,
 .Xr ugold 4 ,
 .Xr uhid 4 ,
diff --git share/man/man4/usb.4 share/man/man4/usb.4
index dad3d3a97d9..d159d8b27f3 100644
--- share/man/man4/usb.4
+++ share/man/man4/usb.4
@@ -249,6 +249,8 @@ D-Link DSB-R100 USB radio device
 FIDO/U2F security keys
 .It Xr ubcmtp 4
 Broadcom trackpad mouse
+.It Xr ucc 4
+USB Consumer Control keyboards
 .It Xr ugold 4
 TEMPer gold HID thermometer and hygrometer
 .It Xr uhid 4
diff --git sys/arch/alpha/conf/GENERIC sys/arch/alpha/conf/GENERIC
index 8af652ce301..54d4a45cd4e 100644
--- sys/arch/alpha/conf/GENERIC
+++ sys/arch/alpha/conf/GENERIC
@@ -107,6 +107,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 
USB HID UART
 ucom*  at uslhcom?
 uhid*  at uhidev?  # USB generic HID support
 fido*  at uhidev?  # FIDO/U2F security key support
+ucc*   at uhidev?  # Consumer Control keyboards
+wskbd* at ucc? mux 1
 ujoy*  at uhidev?  # USB joystick/gamecontroller support
 uhidpp*at uhidev?  # Logitech HID++ Devices
 upd*   at uhidev?  # USB Power Devices sensors
diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
index c0c16f7c986..0d278739ccf 100644
--- sys/arch/amd64/conf/GENERIC
+++ sys/arch/amd64/conf/GENERIC

Re: usbhidctl: add -R flag to dump raw report descriptor bytes

2021-05-30 Thread Anton Lindqvist
On Fri, May 28, 2021 at 09:52:57PM -0500, joshua stein wrote:
> On Wed, 26 May 2021 at 08:13:52 +0200, Anton Lindqvist wrote:
> > On Tue, May 25, 2021 at 08:31:14AM +0200, Anton Lindqvist wrote:
> > > On Mon, May 24, 2021 at 09:17:26AM -0500, joshua stein wrote:
> > > > This is useful for parsing the report descriptor with a different 
> > > > tool to find issues with our HID parser.
> > > > 
> > > > I've found https://eleccelerator.com/usbdescreqparser/ to be 
> > > > helpful.
> > > > 
> > > > 
> > > > diff --git usr.bin/usbhidctl/usbhid.c usr.bin/usbhidctl/usbhid.c
> > > > index 921f211a280..bd0b5da0222 100644
> > > > --- usr.bin/usbhidctl/usbhid.c
> > > > +++ usr.bin/usbhidctl/usbhid.c
> > > > @@ -106,6 +106,11 @@ static struct {
> > > >  #define REPORT_MAXVAL 2
> > > >  };
> > > >  
> > > > +struct report_desc {
> > > > +   uint32_t size;
> > > > +   uint8_t data[1];
> > > > +};
> > > 
> > > This structure is defined in lib/libusbhid/usbvar.h which is not
> > > installed. Maybe it should and avoid this repetition and potential ABI
> > > breaks (quite unlikely but still)?
> > 
> > Another approach which keeps the structure opaque is the extend the
> > usbhid(3) API with something like:
> > 
> > void
> > hid_get_report_desc_data(report_desc_t d, uint8_t **data, uint32_t 
> > *size)
> > {
> > *data = d->data;
> > *size = d->size;
> > }
> 
> Here's a version of that:

ok anton@



Re: panic(9): set panicstr atomically

2021-05-13 Thread Anton Lindqvist
On Wed, May 12, 2021 at 07:08:39PM -0500, Scott Cheloha wrote:
> Hi,
> 
> In a separate mail thread, bluhm@ mentioned that panic(9) does not
> cleanly handle multiple CPUs entering it simultaneously:
> 
> https://marc.info/?l=openbsd-tech=161908805925325=2
> 
> I'm unsure which part of panic(9) is causing the problem he mentions,
> but one obvious issue I see is that panicstr is not set atomically,
> so two CPUs entering panic(9) simultaneously may clobber panicbuf.
> 
> If we set panicstr atomically only one CPU will write panicbuf.
> 
> Thoughts?

I've seen panics caused by syzkaller where panicbuf looks scrambled by
more than one thread writing to the same static buffer. Assigning
panicstr before the vsnprintf() call therefore makes sense. This is also
what NetBSD does, although not as an atomic operation.

ok anton@



unlock lseek(2)

2021-05-01 Thread Anton Lindqvist
Hi,
In August 2019 I tried to unlock lseek(2) which failed since the vnode
lock could not be acquired without holding the kernel lock back then,
found the hard way. claudio@ recently[1] make it possible to acquire a
vnode lock without holding the kernel lock. I therefore would like to
give this another try. The kernel lock is still required around
VOP_GETATTR() as the underlying file system implementations are not
yet^W MP-safe.

Comments? OK?

[1] 
https://github.com/openbsd/src/commit/9d6122f62b6ed32d6c956e1d5269114b2f24ea14

Index: kern/syscalls.master
===
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.209
diff -u -p -r1.209 syscalls.master
--- kern/syscalls.master18 Mar 2021 08:43:38 -  1.209
+++ kern/syscalls.master29 Apr 2021 19:09:58 -
@@ -349,7 +349,7 @@
 197STD { void *sys_mmap(void *addr, size_t len, int prot, \
int flags, int fd, long pad, off_t pos); }
 198INDIR   { quad_t sys___syscall(quad_t num, ...); }
-199STD { off_t sys_lseek(int fd, int pad, off_t offset, \
+199STD NOLOCK  { off_t sys_lseek(int fd, int pad, off_t offset, \
int whence); }
 200STD { int sys_truncate(const char *path, int pad, \
off_t length); }
Index: kern/vfs_vnops.c
===
RCS file: /cvs/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.115
diff -u -p -r1.115 vfs_vnops.c
--- kern/vfs_vnops.c28 Apr 2021 09:53:53 -  1.115
+++ kern/vfs_vnops.c29 Apr 2021 19:09:58 -
@@ -657,7 +657,9 @@ vn_seek(struct file *fp, off_t *offset, 
newoff = fp->f_offset + *offset;
break;
case SEEK_END:
+   KERNEL_LOCK();
error = VOP_GETATTR(vp, , cred, p);
+   KERNEL_UNLOCK();
if (error)
goto out;
newoff = *offset + (off_t)vattr.va_size;



Re: uhidev: allow devices to match specific multiple reports

2021-03-06 Thread Anton Lindqvist
On Fri, Mar 05, 2021 at 08:58:44AM -0600, joshua stein wrote:
> uhidev allows a child device to claim all reports by calling *_match 
> functions with the report id set to UHIDEV_CLAIM_ALLREPORTID.
> 
> umt needs this because it has to access 3 reports which has worked 
> okay up until now because devices with umt and a ukbd have usually 
> presented them on separate uhidev devices.  However, on a new 
> Surface Type Cover device, someone reported that these devices are 
> on the same uhidev meaning if umt attaches, the ukbd device can't.
> 
> To remedy this, probe devices with UHIDEV_CLAIM_MULTIPLE_REPORTID 
> instead and include an array in the uhidev_attach_arg the size of 
> the available reports.  Devices wanting to claim multiple reports 
> just set the indexes in the array to 1 that it wants to claim and 
> uhidev will reserve those, but still probe other devices with each 
> specific unclaimed id.
> 
> umt is modified to do its report finding in its match function so it 
> can claim just the specific reports it needs.

I ran into the same problem while developing uhidpp(4) and added the
uhidev_{set,unset}_report_dev() API. That driver must be able to talk
the device already in the attach routine, meaning that
`sc->sc_subdevs[repid]' must be assigned. So it cannot make fully use of
the claim multiple reportid feature unfortunately.

However, this looks like a sane approach. Tested on my laptop and
everything still attaches just like before. Just one nit below. Either
way ok anton@

> 
> 
> Index: dev/usb/uhidev.c
> ===
> RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
> retrieving revision 1.89
> diff -u -p -u -p -r1.89 uhidev.c
> --- dev/usb/uhidev.c  15 Feb 2021 11:26:00 -  1.89
> +++ dev/usb/uhidev.c  5 Mar 2021 14:51:09 -
> @@ -250,21 +250,27 @@ uhidev_attach(struct device *parent, str
>  
>   uha.uaa = uaa;
>   uha.parent = sc;
> - uha.reportid = UHIDEV_CLAIM_ALLREPORTID;
> + uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
> + uha.nreports = nrepid;
> + uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
>  
> - /* Look for a driver claiming all report IDs first. */
> + /* Look for a driver claiming multiple report IDs first. */
>   dev = config_found_sm(self, , NULL, uhidevsubmatch);
>   if (dev != NULL) {
>   for (repid = 0; repid < nrepid; repid++) {
>   /*
>* Could already be assigned by uhidev_set_report_dev().
>*/
> - if (sc->sc_subdevs[repid] == NULL)
> + if (sc->sc_subdevs[repid] != NULL)
> + continue;
> +
> + if (uha.claimed[repid])
>   sc->sc_subdevs[repid] = (struct uhidev *)dev;
>   }
> - return;
>   }
>  
> + free(uha.claimed, M_TEMP, nrepid);

I would put a `uha.claimed = NULL` here.



Re: uhidpp(4): logitech hid++ device driver

2021-02-14 Thread Anton Lindqvist
On Fri, Feb 12, 2021 at 03:48:51AM -0800, Anindya Mukherjee wrote:
> Hi,
> 
> Sorry for the delay. I am running the latest snapshot:
> kern.version=OpenBSD 6.9-beta (GENERIC.MP) #331: Thu Feb 11 20:28:45 MST 2021
> dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> which seems to have the latest updates. However I still do not see battery
> levels for my M570. Full dmesg below. Please let me know if I can test 
> anything.

Could you try a kernel with revision 1.10 of dev/usb/uhidpp.c present
and UHIDPP_DEBUG enabled. I have also prepared an amd64 kernel with the
necessary bits available here:

https://www.basename.se/tmp/bsd.uhidpp

Please send me the complete dmesg from this kernel. It won't make any
battery sensors appear but rather help diagnose.



Re: interface group name validation

2021-02-09 Thread Anton Lindqvist
On Tue, Feb 09, 2021 at 11:08:09PM +0100, Alexander Bluhm wrote:
> Hi,
> 
> Next try to fix syzkaller crash
> https://syzkaller.appspot.com/bug?id=54e16dc5bce6929e14b42e2f1379f1c18f62be43
> 
> Interface group names must fit into IFNAMSIZ and be unique.  But
> the kernel makes the unique check before trunkating with strlcpy().
> So there can be two interfaces groups with the same name.  The kif
> is created by a name lookup.  The trunkated names are equal so there
> is only one kif owned by both groups.  When both groups are destroyed,
> the single kif is removed twice from the RB tree.
> 
> - Check length of group name before doing the unique check.
> - The empty group name was allowed.  That does not make much sense.
>   Does anyone use the empty interface group?
> - Use the same check in kernel and ifconfig userland.
> - ifconfig -group does not need name sanitation.  The kernel will
>   just report that it does not exist.
> 
> ok?

syzkaller was not able to trigger the panic using the syz reproducer
with your diff applied:


https://groups.google.com/g/syzkaller-openbsd-bugs/c/ZhqISaYBvVE/m/G-V3cB9OAgAJ

ok anton@



Re: uhidpp(4): logitech hid++ device driver

2021-02-08 Thread Anton Lindqvist
Hi,

On Mon, Feb 08, 2021 at 02:50:39PM -0800, Anindya Mukherjee wrote:
> Hi, I have a Logitech M570 which seems to be handled by this new driver.
> However I don't see any battery level information.
> 
> dmesg:
> uhidpp0 at uhidev4 device 1 mouse "M570" serial ef-81-ff-80
> 
> sysctl kern.version:
> kern.version=OpenBSD 6.8-current (GENERIC.MP) #313: Fri Feb  5 18:31:44 MST 
> 2021
> dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
> hw.sensors.uhidpp0 does not seem to exist.
> 
> Regards,
> Anindya
> 

Could you try the following diff and send me the complete dmesg. I've
also prepared an amd64 kernel with the patch applied:

https://www.basename.se/tmp/bsd.uhidpp.battery

diff --git sys/dev/usb/uhidpp.c sys/dev/usb/uhidpp.c
index b041d86fecd..27f6137ec06 100644
--- sys/dev/usb/uhidpp.c
+++ sys/dev/usb/uhidpp.c
@@ -29,7 +29,7 @@
 #include 
 #include 
 
-/* #define UHIDPP_DEBUG */
+#define UHIDPP_DEBUG
 #ifdef UHIDPP_DEBUG
 
 #define DPRINTF(x...) do { \
@@ -84,12 +84,16 @@ int uhidpp_debug = 1;
 #define HIDPP_GET_LONG_REGISTER0x83
 
 #define HIDPP_REG_ENABLE_REPORTS   0x00
+#define HIDPP_REG_BATTERY_STATUS   0x07
 #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)
 
+/* Number of battery levels supported by HID++ 1.0 devices. */
+#define HIDPP_BATTERY_NLEVELS  7
+
 /* HID++ 1.0 error codes. */
 #define HIDPP_ERROR0x8f
 #define HIDPP_ERROR_SUCCESS0x00
@@ -112,7 +116,6 @@ int uhidpp_debug = 1;
  * 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
@@ -154,8 +157,8 @@ int uhidpp_debug = 1;
 
 /* Feature access report used by the HID++ 2.0 (and greater) protocol. */
 struct fap {
-   uint8_t feature_index;
-   uint8_t funcindex_clientid;
+   uint8_t feature_idx;
+   uint8_t funcidx_swid;
uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX];
 };
 
@@ -185,6 +188,8 @@ struct uhidpp_notification {
 struct uhidpp_device {
uint8_t d_id;
uint8_t d_connected;
+   uint8_t d_major;
+   uint8_t d_minor;
struct {
struct ksensor b_sens[UHIDPP_NSENSORS];
uint8_t b_feature_idx;
@@ -237,8 +242,10 @@ 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 hidpp_get_protocol_version(struct uhidpp_softc  *, uint8_t, uint8_t *,
+uint8_t *);
 
+int hidpp10_get_battery_status(struct uhidpp_softc *, uint8_t, uint8_t *);
 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 **);
@@ -520,7 +527,7 @@ void
 uhidpp_device_connect(struct uhidpp_softc *sc, struct uhidpp_device *dev)
 {
struct ksensor *sens;
-   int error, major, minor;
+   int error;
uint8_t feature_type;
 
MUTEX_ASSERT_LOCKED(>sc_mtx);
@@ -529,30 +536,40 @@ uhidpp_device_connect(struct uhidpp_softc *sc, struct 
uhidpp_device *dev)
if (dev->d_connected)
return;
 
-   error = hidpp_get_protocol_version(sc, dev->d_id, , );
+   error = hidpp_get_protocol_version(sc, dev->d_id,
+   >d_major, >d_minor);
if (error) {
-   DPRINTF("%s: protocol version failure: device_id=%d, 
error=%d\n",
+   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);
+   __func__, dev->d_id, dev->d_major, dev->d_minor);
 
-   error = hidpp20_root_get_feature(sc, dev->d_id,
-   HIDPP20_FEAT_BATTERY_IDX,
-   >d_battery.b_feature_idx, _type);
-   if (error) {
-   DPRINTF("%s: battery feature index failure: device_id=%d, "
-   "error=%d\n", __func__, dev->d_id, error);
-   return;
-   }
+   if (dev->d_major >= 2) {
+   error = hidpp20_root_get_feature(sc, dev->d_id,
+   HIDPP20_FEAT_BATTERY_IDX,
+   >d_battery.b_feature_idx, _type);
+   if (error) {
+   

Re: uhidpp(4): logitech hid++ device driver

2021-02-05 Thread Anton Lindqvist
On Fri, Feb 05, 2021 at 10:36:34AM +0100, Landry Breuil wrote:
> On Fri, Jan 22, 2021 at 08:18:51AM +0100, Anton Lindqvist wrote:
> > Hi,
> > Here's a new driver for Logitech HID++ devices, currently limited to
> > exposing battery sensors. Here's an example using a Logitech M330 mouse:
> > 
> > $ dmesg | grep uhidpp
> > uhidpp0 at uhidev1 device 1 mouse "B330/M330/M3" serial c7-2f-a8-33
> > $ sysctl hw.sensors.uhidpp0
> > hw.sensors.uhidpp0.raw0=2 (battery levels)
> > hw.sensors.uhidpp0.percent0=70.00% (battery level), OK
> 
> thanks anton, now that this got commited i realize i have a pair of
> devices:
> 
> device 1 (M235 according to bottom) previously reported this in dmesg:
> 
> uhidev0 at uhub0 port 2 configuration 1 interface 0 "Logitech USB Receiver" 
> rev 2.00/12.03 addr 2
> uhidev0: iclass 3/1
> ukbd0 at uhidev0: 8 variable keys, 6 key codes
> wskbd1 at ukbd0 mux 1
> uhidev1 at uhub0 port 2 configuration 1 interface 1 "Logitech USB Receiver" 
> rev 2.00/12.03 addr 2
> 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 2 configuration 1 interface 2 "Logitech USB Receiver" 
> rev 2.00/12.03 addr 2
> uhidev2: iclass 3/0, 33 report ids
> uhid3 at uhidev2 reportid 16: input=6, output=6, feature=0
> uhid4 at uhidev2 reportid 17: input=19, output=19, feature=0
> uhid5 at uhidev2 reportid 32: input=14, output=14, feature=0
> uhid6 at uhidev2 reportid 33: input=31, output=31, feature=0
> 
> device 2 (M235 2nd gen according to bottom) previously reported this in dmesg
> (same thing, but the rev/addr values):
> 
> uhidev1 at uhub0 port 4 configuration 1 interface 0 "Logitech USB Receiver" 
> rev 2.00/24.07 addr 3
> uhidev1: iclass 3/1
> ukbd1 at uhidev1: 8 variable keys, 6 key codes
> wskbd2 at ukbd1 mux 1
> uhidev2 at uhub0 port 4 configuration 1 interface 1 "Logitech USB Receiver" 
> rev 2.00/24.07 addr 3
> uhidev2: iclass 3/1, 8 report ids
> ums0 at uhidev2 reportid 2: 16 buttons, Z and W dir
> wsmouse2 at ums0 mux 0
> uhid0 at uhidev2 reportid 3: input=4, output=0, feature=0
> uhid1 at uhidev2 reportid 4: input=1, output=0, feature=0
> uhid2 at uhidev2 reportid 8: input=1, output=0, feature=0
> uhidev3 at uhub0 port 4 configuration 1 interface 2 "Logitech USB Receiver" 
> rev 2.00/24.07 addr 3
> uhidev3: iclass 3/0, 33 report ids
> uhid3 at uhidev3 reportid 16: input=6, output=6, feature=0
> uhid4 at uhidev3 reportid 17: input=19, output=19, feature=0
> uhid5 at uhidev3 reportid 32: input=14, output=14, feature=0
> uhid6 at uhidev3 reportid 33: input=31, output=31, feature=0
> 
> now device 1/uhidev2 is properly identified by uhidpp:
> 
> uhidev2 at uhub0 port 2 configuration 1 interface 2 "Logitech USB Receiver" 
> rev 2.00/12.03 addr 2
> uhidev2: iclass 3/0, 33 report ids
> uhidpp0 at uhidev2 device 1 mouse "M325" serial 69-b1-af-84
> 
> and properly reports sensors:
> hw.sensors.uhidpp0.raw0=2 (battery levels)
> hw.sensors.uhidpp0.percent0=70.00% (battery level), OK
> 
> and device2 (plugged on the same laptop so device renumbered) also works with 
> uhidpp:
> 
> uhidev2 at uhub0 port 2 configuration 1 interface 2 "Logitech USB Receiver" 
> rev 2.00/24.07 addr 2
> uhidev2: iclass 3/0, 33 report ids
> uhidpp0 at uhidev2 device 1 mouse "Wireless Mouse" serial f3-94-18-8c
> 
> same level reported in sensors for a different mouse (?):
> hw.sensors.uhidpp0.raw0=2 (battery levels)
> hw.sensors.uhidpp0.percent0=70.00% (battery level), OK
> 
> let me know if you need more details/infos from those devices (usbdevs dumps 
> etc..)

As both your devices only are capable of reporting two battery levels,
as given by hw.sensors.uhidpp0.raw0, it's quite likely that they will
report the same level.

> i'll eventually look at adding support for uhidpp to upower so mouse battery
> levels can be reported in xfce4-power-manager and gnome, like it does on
> linux..

There has been some work on this from a Linux perspective[1], not sure
if there's anything you could piggy back on there. Let me know if any
more data needs to be expsoed in order to satisfy upower.

[1] https://julien.danjou.info/logitech-unifying-upower/



Re: uhidpp(4): logitech hid++ device driver

2021-02-02 Thread Anton Lindqvist
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:
> > > 
> > > 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]
> > > 
> > > 
> >

Re: uhidpp(4): logitech hid++ device driver

2021-02-01 Thread Anton Lindqvist
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:
> 
> 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]
> 
> 
> 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?

> Btw. Time has passed since my previous

Re: uhidpp(4): logitech hid++ device driver

2021-01-29 Thread Anton Lindqvist
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.



Re: uhidpp(4): logitech hid++ device driver

2021-01-29 Thread Anton Lindqvist
On Fri, Jan 29, 2021 at 07:23:37PM +0200, Ville Valkonen wrote:
> Hello Anton,
> 
> either I failed to use git or then files have changed since the first patch:
> $ git apply -p0 --check hid_plusplus.patch
> error: patch failed: share/man/man4/Makefile:83
> error: share/man/man4/Makefile: patch does not apply
> error: patch failed: share/man/man4/uhidev.4:40
> error: share/man/man4/uhidev.4: patch does not apply
> error: patch failed: share/man/man4/usb.4:255
> error: share/man/man4/usb.4: patch does not apply
> error: patch failed: sys/arch/amd64/conf/GENERIC:288
> error: sys/arch/amd64/conf/GENERIC: patch does not apply
> error: patch failed: sys/dev/usb/uhidev.c:950
> error: sys/dev/usb/uhidev.c: patch does not apply
> error: sys/dev/usb/uhidpp.c: already exists in working directory
> 
> Running that on root of src. A quick peek on sys/dev/usb/uhidev.c file
> shows that it has been modified on 25th of Jan so I'd guess the patch
> needs to be updated.
> 
> Thanks in advance! Been thinking to have a look on that protocol but
> since I am no HW hacker I've postponed that for years :)

Rebased diff, should apply using either git-apply or patch.

diff --git share/man/man4/Makefile share/man/man4/Makefile
index 70e62135237..f893825ceb9 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 000..4c78380c35b
--- /dev/null
+++ share/man/man4/uhidpp.4
@@ -0,0 +1,48 @@
+.\"$OpenBSD$
+.\"
+.\" Copyright (c) 2021 Anton Lindqvsit 
+.\"
+.\" 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 an...@opensd.org .
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/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
index ffa1b4a497c..643e6bd0ba1 100644
--- sys/arch/amd64/conf/GENERIC
+++ sys/arch/amd64/conf/GENERIC
@@ -289,6 +289,7 @@ fido*   at uhidev?  # FIDO/U2F secu

Re: uhidpp(4): logitech hid++ device driver

2021-01-28 Thread Anton Lindqvist
Ping

On Fri, Jan 22, 2021 at 08:18:51AM +0100, Anton Lindqvist wrote:
> Hi,
> Here's a new driver for Logitech HID++ devices, currently limited to
> exposing battery sensors. Here's an example using a Logitech M330 mouse:
> 
>   $ dmesg | grep uhidpp
>   uhidpp0 at uhidev1 device 1 mouse "B330/M330/M3" serial c7-2f-a8-33
>   $ sysctl hw.sensors.uhidpp0
>   hw.sensors.uhidpp0.raw0=2 (battery levels)
>   hw.sensors.uhidpp0.percent0=70.00% (battery level), OK
> 
> The raw0 sensor reflects number of available battery levels, the
> resolution on this device is not great...
> 
> Most of the code is derived from the hid-logitech-hidpp Linux driver.
> Some assorted notes:
> 
> * In order to communicate with the device inside the attach routine, I
>   had to wire up the interrupt handler as this by default is done first
>   once the same attach routine has returned. Hence the introduction of
>   uhidev_set_intr(). If this is an acceptable approach, this can go in
>   as a separate commit.
> 
> * I kept using the `return -errno' convention from the Linux driver in
>   order to distingush errors from the hardware, which are always
>   positive.
> 
> I you happen to have a Logitech HID++ device and run into any
> problem(s), please enable UHIDPP_DEBUG and send me the output.
> 
> Comments? OK?
> 
> diff --git share/man/man4/Makefile share/man/man4/Makefile
> index 02af7a47a44..74a4e17d7dc 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 \
> - uk.4 ukbd.4 \
> + uftdi.4 ugen.4 ugl.4 ugold.4 uguru.4 uhci.4 uhid.4 uhidev.4 uhidpp.4 \
> + uipaq.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 f0a6776a27b..d264935a65c 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 "ukbd*at uhidev?"
>  .Cd "ums* at uhidev?"
>  .Cd "umstc*   at uhidev?"
> @@ -73,6 +74,7 @@ only dispatches data to them based on the report id.
>  .Xr ucycom 4 ,
>  .Xr ugold 4 ,
>  .Xr uhid 4 ,
> +.Xr uhidpp 4 ,
>  .Xr ukbd 4 ,
>  .Xr ums 4 ,
>  .Xr umstc 4 ,
> diff --git share/man/man4/uhidpp.4 share/man/man4/uhidpp.4
> new file mode 100644
> index 000..4c78380c35b
> --- /dev/null
> +++ share/man/man4/uhidpp.4
> @@ -0,0 +1,48 @@
> +.\"  $OpenBSD$
> +.\"
> +.\" Copyright (c) 2021 Anton Lindqvsit 
> +.\"
> +.\" 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 an...@opensd.org .
> diff --git share/man/man

usbhidctl: efault

2021-01-28 Thread Anton Lindqvist
Hi,
While running usbhidctl on my USB mouse it occasionally fails as
follows:

# usbhidctl -f /dev/wsmouse2 
usbhidctl: USB_GET_REPORT (probably not supported by device): Bad 
address

The EFAULT happens during copyin(9) in sys_ioctl() while copying the
supplied usb_ctl_report structure which is declared as follows:

struct usb_ctl_report {
int ucr_report;
u_char  ucr_data[1024]; /* filled data size will vary */
};

... and the corresponding ioctl command:

#define USB_GET_REPORT  _IOWR('U', 23, struct usb_ctl_report)

usbhidctl tries to be memory efficient by only allocating a buffer big
enough to hold the requested report. Such report is often smaller than
1024 bytes.

However, the kernel will always copy `sizeof(struct usb_ctl_report)'
bytes from the address passed from user space. I would assume the EFAULT
happens when `addr + sizeof(struct usb_ctl_report)' crosses a page
boundary and the adjacent page is not mapped. Unconditionally allocating
the correct size fixes the problem.

Comments? OK?

Index: usbhid.c
===
RCS file: /cvs/src/usr.bin/usbhidctl/usbhid.c,v
retrieving revision 1.15
diff -u -p -r1.15 usbhid.c
--- usbhid.c28 Jun 2019 13:35:05 -  1.15
+++ usbhid.c28 Jan 2021 20:27:17 -
@@ -394,13 +394,7 @@ allocreport(struct Sreport *report, repo
report->size = reptsize;
 
if (report->size > 0) {
-   /*
-* Allocate a buffer with enough space for the
-* report in the variable-sized data field.
-*/
-   report->buffer = malloc(sizeof(*report->buffer) -
-   sizeof(report->buffer->ucr_data) +
-   report->size);
+   report->buffer = malloc(sizeof(*report->buffer));
if (report->buffer == NULL)
err(1, NULL);
} else



uhidpp(4): logitech hid++ device driver

2021-01-22 Thread Anton Lindqvist
Hi,
Here's a new driver for Logitech HID++ devices, currently limited to
exposing battery sensors. Here's an example using a Logitech M330 mouse:

$ dmesg | grep uhidpp
uhidpp0 at uhidev1 device 1 mouse "B330/M330/M3" serial c7-2f-a8-33
$ sysctl hw.sensors.uhidpp0
hw.sensors.uhidpp0.raw0=2 (battery levels)
hw.sensors.uhidpp0.percent0=70.00% (battery level), OK

The raw0 sensor reflects number of available battery levels, the
resolution on this device is not great...

Most of the code is derived from the hid-logitech-hidpp Linux driver.
Some assorted notes:

* In order to communicate with the device inside the attach routine, I
  had to wire up the interrupt handler as this by default is done first
  once the same attach routine has returned. Hence the introduction of
  uhidev_set_intr(). If this is an acceptable approach, this can go in
  as a separate commit.

* I kept using the `return -errno' convention from the Linux driver in
  order to distingush errors from the hardware, which are always
  positive.

I you happen to have a Logitech HID++ device and run into any
problem(s), please enable UHIDPP_DEBUG and send me the output.

Comments? OK?

diff --git share/man/man4/Makefile share/man/man4/Makefile
index 02af7a47a44..74a4e17d7dc 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 \
-   uk.4 ukbd.4 \
+   uftdi.4 ugen.4 ugl.4 ugold.4 uguru.4 uhci.4 uhid.4 uhidev.4 uhidpp.4 \
+   uipaq.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 f0a6776a27b..d264935a65c 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 "ukbd*at uhidev?"
 .Cd "ums* at uhidev?"
 .Cd "umstc*   at uhidev?"
@@ -73,6 +74,7 @@ only dispatches data to them based on the report id.
 .Xr ucycom 4 ,
 .Xr ugold 4 ,
 .Xr uhid 4 ,
+.Xr uhidpp 4 ,
 .Xr ukbd 4 ,
 .Xr ums 4 ,
 .Xr umstc 4 ,
diff --git share/man/man4/uhidpp.4 share/man/man4/uhidpp.4
new file mode 100644
index 000..4c78380c35b
--- /dev/null
+++ share/man/man4/uhidpp.4
@@ -0,0 +1,48 @@
+.\"$OpenBSD$
+.\"
+.\" Copyright (c) 2021 Anton Lindqvsit 
+.\"
+.\" 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 an...@opensd.org .
diff --git share/man/man4/usb.4 share/man/man4/usb.4
index 520f46265e0..b58190539e3 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 ukbd 4
 USB keyboards that follow the boot protocol
 .It Xr ums 4
diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
index 45b3a9b6e66..00ac52adcd6 100644
--- sys/arch/amd64/conf/GENERIC
+++ sys/arch/amd64/conf/GENERIC
@@ -288,6 +288,7 @@ uhid*   at uhidev?  # USB generic HID 
support

usb_init_task(9): correct type

2021-01-15 Thread Anton Lindqvist
Hi,
The usb_init_task(9) macro accepts a `struct usb_task'.

Comments? OK?

Index: share/man/man9/usb_add_task.9
===
RCS file: /cvs/src/share/man/man9/usb_add_task.9,v
retrieving revision 1.2
diff -u -p -r1.2 usb_add_task.9
--- share/man/man9/usb_add_task.9   15 Sep 2016 18:26:22 -  1.2
+++ share/man/man9/usb_add_task.9   16 Jan 2021 06:59:49 -
@@ -35,7 +35,7 @@
 .Ft void
 .Fn usb_rem_wait_task "struct usbd_device *dev" "struct usb_task *task"
 .Ft void
-.Fn usb_init_task "struct usbd_device *dev" "void (*fn)(void *)" "void *arg" 
"char type"
+.Fn usb_init_task "struct usb_task *task" "void (*fn)(void *)" "void *arg" 
"char type"
 .Sh DESCRIPTION
 The USB stack provides an API to manage task execution in a thread context at
 the soonest opportunity.



Re: unbound: missing null check

2021-01-06 Thread Anton Lindqvist
On Wed, Jan 06, 2021 at 10:24:47AM +0100, Florian Obser wrote:
> On Wed, Jan 06, 2021 at 10:11:01AM +0100, Anton Lindqvist wrote:
> > Hi,
> > I have a unbound forward zone configured on my router for my $DAYJOB.
> > The address associated with the zone is only accessible when the router
> > is connected to a VPN. If the VPN connection is absent, trying to
> > resolve any domain that must be handled by the zone crashes unbound.
> > Turns out there's a missing NULL check in comm_point_send_udp_msg().
> > The same routine already has `if (addr) {} else {}' branches so I guess
> > protecting the call to log_addr() using the same conditional is
> > reasonable.
> > 
> > Should this instead be upstreamed? Comments? OK?
> 
> yes, please upstream it.

Pending pull request submitted:

  https://github.com/NLnetLabs/unbound/pull/395

> Could you also do sbin/unwind/libunbound/util/netevent.c?

Sure, done.



unbound: missing null check

2021-01-06 Thread Anton Lindqvist
Hi,
I have a unbound forward zone configured on my router for my $DAYJOB.
The address associated with the zone is only accessible when the router
is connected to a VPN. If the VPN connection is absent, trying to
resolve any domain that must be handled by the zone crashes unbound.
Turns out there's a missing NULL check in comm_point_send_udp_msg().
The same routine already has `if (addr) {} else {}' branches so I guess
protecting the call to log_addr() using the same conditional is
reasonable.

Should this instead be upstreamed? Comments? OK?

Index: util/netevent.c
===
RCS file: /cvs/src/usr.sbin/unbound/util/netevent.c,v
retrieving revision 1.27
diff -u -p -r1.27 netevent.c
--- util/netevent.c 10 Dec 2020 21:44:58 -  1.27
+++ util/netevent.c 6 Jan 2021 09:03:59 -
@@ -379,8 +379,9 @@ comm_point_send_udp_msg(struct comm_poin
if(!udp_send_errno_needs_log(addr, addrlen))
return 0;
verbose(VERB_OPS, "sendto failed: %s", sock_strerror(errno));
-   log_addr(VERB_OPS, "remote address is", 
-   (struct sockaddr_storage*)addr, addrlen);
+   if(addr)
+   log_addr(VERB_OPS, "remote address is",
+   (struct sockaddr_storage*)addr, addrlen);
return 0;
} else if((size_t)sent != sldns_buffer_remaining(packet)) {
log_err("sent %d in place of %d bytes", 



Re: Use SMR_TAILQ for `ps_threads'

2020-12-02 Thread Anton Lindqvist
On Wed, Dec 02, 2020 at 11:41:04AM -0300, Martin Pieuchot wrote:
> On 02/12/20(Wed) 17:27, Jonathan Matthew wrote:
> > On Tue, Dec 01, 2020 at 02:35:18PM -0300, Martin Pieuchot wrote:
> > > On 01/12/20(Tue) 15:30, Claudio Jeker wrote:
> > > > [...] 
> > > > Did you run a make build with that smr_barrier() in it and checked that 
> > > > it
> > > > does not cause a slow down? I am sceptical, smr_barrier() is a very slow
> > > > construct which introduces large delays and should be avoided whenever
> > > > possible.
> > > 
> > > I did build GENERIC.MP multiple times on a 4CPU sparc64 with the diff
> > > below, without noticeable difference.
> > > 
> > > I'm happy to hear from sceptical performance checkers :o)
> > 
> > On a reasonably fast amd64 box, this increases GENERIC.MP make -j6 build 
> > time from
> > ~3m06s to ~3m44s, which seems a bit much to me.
> 
> Do you know if this is due to an increase of %spin time?
> 
> > Replacing smr_barrier() with smr_flush() reduces the overhead to a couple of
> > seconds, and it seems warranted here.
> 
> Could you try the diff below that only call smr_barrier() for multi-
> threaded processes with threads still in the list.  I guess this also
> answers guenther@'s question.  The same could be done with smr_flush().

I'm wondering if smr_grace_wait() could be improved on amd64, assuming
SMT is disabled, by skipping offline CPUs.

Index: kern/kern_smr.c
===
RCS file: /cvs/src/sys/kern/kern_smr.c,v
retrieving revision 1.8
diff -u -p -r1.8 kern_smr.c
--- kern/kern_smr.c 3 Apr 2020 03:36:56 -   1.8
+++ kern/kern_smr.c 2 Dec 2020 18:41:29 -
@@ -142,7 +142,7 @@ smr_grace_wait(void)
 
ci_start = curcpu();
CPU_INFO_FOREACH(cii, ci) {
-   if (ci == ci_start)
+   if (ci == ci_start || !cpu_is_online(ci))
continue;
sched_peg_curproc(ci);
}



Re: ksh tab completion bug

2020-11-10 Thread Anton Lindqvist
On Tue, Nov 10, 2020 at 06:49:28PM +0100, Sven M. Hallberg wrote:
> Apologies for jumping in as a bystander, but if I may comment:
> 
> Anton Lindqvist on Tue, Nov 10 2020:
> > Been brought up before[1] and rejected[2][3].
> 
> Anton Lindqvist on Sun, Jul 02, 2017:
> > diff below in which slashes are discarded when comparing the length. I
> > don't know if any other character should be discarded as well, if true
> > then it might be worth passing the input buffer through ksh's own
> > lexer and [...]
> 
> The patch then seems to have been rejected for further complicating some
> already hairy code and the above does sound rather unsafe.
> 
> Michael's aim here appears to be to simplify things:
> 
> Michael Forney on Mon, Nov 09, 2020:
> > emacs.c:do_complete() using `end - start` for olen (which counts the
> > backslashes), but nlen (the longest prefix length) does not. [...]
> >
> > I don't believe vi.c:complete_word() has this issue [...]
> > 
> > [my diff] is longer than I had hoped. Perhaps there is a simpler patch
> > to make emacs.c:do_complete() use the same approach as vi completion.
> 
> Maybe some iteration is all that is needed.

I not saying the diff is bad in anyway, just sharing a related data
point. I do think this would be an improvement and the approach looks
better than mine.

As I would address this, the numbers of arguments passed to the
completion related routines is already painfully^W long. I would rather
take a step back and introduce a `struct globstate' (just an example,
could be renamed) which includes all the necessary parameters. Getting
such refactoring in place first would make the diff even smaller.

Also, emacs mode has its own regress suite located in
regress/bin/ksh/edit/emacs.sh. Tricky logic like this should be covered
in my opinion. Below is a rough diff how to test file name completion.

Michael, is this something you would like to continue work on?

Index: emacs.sh
===
RCS file: /cvs/src/regress/bin/ksh/edit/emacs.sh,v
retrieving revision 1.11
diff -u -p -r1.11 emacs.sh
--- emacs.sh3 Apr 2019 14:59:34 -   1.11
+++ emacs.sh10 Nov 2020 19:53:30 -
@@ -139,7 +139,11 @@ testseq "a\0033#" " # a\r # #a \0010\001
 
 # XXX ^[^[: complete
 # XXX ^X^[: complete-command
-# XXX ^[^X: complete-file
+
+# ^[^X: complete-file
+: >abc
+testseq "ls \0033\0030" " # abc"
+
 # XXX ^I, ^[=: complete-list
 
 # [n] ERASE, ^?, ^H: delete-char-backward
Index: subr.sh
===
RCS file: /cvs/src/regress/bin/ksh/edit/subr.sh,v
retrieving revision 1.8
diff -u -p -r1.8 subr.sh
--- subr.sh 21 Nov 2017 19:25:46 -  1.8
+++ subr.sh 10 Nov 2020 19:53:30 -
@@ -18,7 +18,7 @@
 testseq() {
stdin=$1
exp=$(echo "$2")
-   act=$(echo -n "$stdin" | ./edit -p "$PS1" ${KSH:-/bin/ksh} -r 2>&1)
+   act=$(echo -n "$stdin" | "$EDIT" -p "$PS1" ${KSH:-/bin/ksh} -r 2>&1)
[ $? = 0 ] && [ "$exp" = "$act" ] && return 0
 
dump input "$stdin"
@@ -32,3 +32,9 @@ dump() {
printf '%s:\n>>>%s<<<\n' "$1" "$(echo -n "$2" | vis -ol)"
echo -n "$2" | hexdump -Cv
 }
+
+EDIT="${PWD}/edit"
+
+TMP="$(mktemp -dt ksh.XX)"
+trap 'rm -r $TMP' EXIT
+cd "$TMP"



Re: ksh tab completion bug

2020-11-09 Thread Anton Lindqvist
On Mon, Nov 09, 2020 at 11:15:36PM -0800, Michael Forney wrote:
> I noticed some strange behavior of ksh in emacs mode when completing
> file names that contain spaces (or other characters that need
> escaping).
> 
> To illustrate the problem, consider two files 'a b c test1' and
> 'a b c test2'. ksh will correctly complete `a` and `a\ b\ c\ ` to
> the common prefix `a\ b\ c\ test`. However, all of the following
> do not get completed:
> 
> * `a\ b\ c\ t`
> * `a\ b\ c\ te`
> * `a\ b\ c\ tes`
> 
> I did some debugging, and I think this is due to emacs.c:do_complete()
> using `end - start` for olen (which counts the backslashes), but
> nlen (the longest prefix length) does not. So the completion only
> occurs when the current word is shorter than the common prefix
> length minus the number of backslashes in the word.
> 
> I don't believe vi.c:complete_word() has this issue since it always
> replaces the word with the longest prefix.
> 
> I wrote a (only lightly tested) patch to make x_cf_glob return the
> unescaped length as well as the start and end positions, and use
> that for olen instead of `end - start`. This seems to fix the issue,
> but it is longer than I had hoped. Perhaps there is a simpler patch
> to make emacs.c:do_complete() use the same approach as vi completion.

Been brought up before[1] and rejected[2][3].

[1] https://marc.info/?l=openbsd-bugs=149902839123905=2
[2] https://marc.info/?l=openbsd-bugs=149925960003395=2
[3] https://marc.info/?l=openbsd-bugs=149925991603581=2



Re: process: annotate locking for setitimer(2) state

2020-08-11 Thread Anton Lindqvist
On Sun, Aug 09, 2020 at 05:33:58PM +0200, Mark Kettenis wrote:
> > Date: Sun, 9 Aug 2020 10:02:38 -0500
> > From: Scott Cheloha 
> > 
> > On Sun, Aug 09, 2020 at 04:43:24PM +0200, Mark Kettenis wrote:
> > > > Date: Sat, 8 Aug 2020 19:46:14 -0500
> > > > From: Scott Cheloha 
> > > > 
> > > > Hi,
> > > > 
> > > > I want to annotate the locking for the per-process interval timers.
> > > > 
> > > > In the process struct, the ITIMER_REAL itimerspec and the ps_itimer_to
> > > > timeout are protected by the kernel lock.  These should be annotated
> > > > with "K", right?
> > > > 
> > > > Also in the process struct, the ITIMER_VIRTUAL and ITIMER_PROF
> > > > itimerspecs are protected by the global itimer_mtx.
> > > > 
> > > > However, I don't think "itimer_mtx" isn't the best name for it, as it
> > > > doesn't protect state for *all* per-process interval timers.  Just the
> > > > virtual ones.
> > > > 
> > > > Could I rename the mutex to "virtual_itimer_mtx"?  Then I can annotate
> > > > the state protected by it with "V", as shown here in this patch.
> > > 
> > > That's quite a long variable name though.  And it also protects
> > > ITIMER_PROF.  So I'd say the name would be at least as misleading as
> > > the current one and perhaps even more so.  You can just use "I" as the
> > > annotation perhaps?
> > 
> > The convention is to use "I" for immutable variables.  We do it
> > everywhere.  I don't think we should buck convention here.
> > 
> > I also proposed using "i" in a prior patch to annotate these
> > variables, but mpi@ said it was too close to "I".  Also, it's a global
> > lock, and we have settled on only annotate global locks with capital
> > letters.
> > 
> > If you don't want to rename the mutex I guess we could use "T" for
> > "timer".  We use "T" for other global locks (tc_lock, timeout_mutex)
> > but not in this context.
> > 
> > However, there are only so many letters.  Eventually this scheme will
> > run afoul of that limitation.  An idea I had re. the letter shortage
> > was to use two letters where necessary.  So instead of "I" you could
> > use "It" for "itimer".  We annotate locking hierarchies with commas so
> > there isn't an ambiguity when reading it.
> > 
> > For example, if the code for writing a hypothetical "ps_foo" process
> > struct member was:
> > 
> > KERNEL_LOCK();
> > mtx_enter(_mtx);
> > ps.ps_foo = 10;
> > mtx_leave(_mtx);
> > KERNEL_UNLOCK();
> > 
> > You could annotate it like this:
> > 
> > /*
> >  * Locks used to protect process struct members:
> >  *
> >  *  It  itimer_mtx
> >  *  K   kernel lock
> >  */
> > struct process {
> > /* [...] */
> > int ps_foo; /* [K,It] per-process foobar */
> > /* [...] */
> > };
> > 
> > anton@, mpi@: is that too radical or easily misread?
> > 
> > Sorry if this all seems fussy, but I'd like to get this right the
> > first time.
> 
> 'T' is fine with me.  But I'm clearly not an authority here.  Anyway,
> renaming variables because you don't have a matching letter to
> annotate the lock doesn't feel right.

I'm also fine with T.



harmonize locking annotations

2020-06-29 Thread Anton Lindqvist
Hi,
I think we all agree that global locks should be represented using
uppercase letters in locking annotations. This is an attempt to
harmonize the existing annotations.

Comments? OK?

Index: dev/dt/dt_dev.c
===
RCS file: /cvs/src/sys/dev/dt/dt_dev.c,v
retrieving revision 1.7
diff -u -p -r1.7 dt_dev.c
--- dev/dt/dt_dev.c 27 Jun 2020 07:22:09 -  1.7
+++ dev/dt/dt_dev.c 29 Jun 2020 18:47:30 -
@@ -74,19 +74,19 @@
  *
  *  Locks used to protect struct members in this file:
  * m   per-softc mutex
- * k   kernel lock
+ * K   kernel lock
  */
 struct dt_softc {
-   SLIST_ENTRY(dt_softc)ds_next;   /* [k] descriptor list */
+   SLIST_ENTRY(dt_softc)ds_next;   /* [K] descriptor list */
int  ds_unit;   /* [I] D_CLONE unique unit */
pid_tds_pid;/* [I] PID of tracing program */
 
struct mutex ds_mtx;
 
-   struct dt_pcb_list   ds_pcbs;   /* [k] list of enabled PCBs */
-   struct dt_evt   *ds_bufqueue;   /* [k] copy evts to userland */
-   size_t   ds_bufqlen;/* [k] length of the queue */
-   int  ds_recording;  /* [k] currently recording? */
+   struct dt_pcb_list   ds_pcbs;   /* [K] list of enabled PCBs */
+   struct dt_evt   *ds_bufqueue;   /* [K] copy evts to userland */
+   size_t   ds_bufqlen;/* [K] length of the queue */
+   int  ds_recording;  /* [K] currently recording? */
int  ds_evtcnt; /* [m] # of readable evts */
 
/* Counters */
@@ -94,7 +94,7 @@ struct dt_softc {
uint64_t ds_dropevt;/* [m] # of events dropped */
 };
 
-SLIST_HEAD(, dt_softc) dtdev_list; /* [k] list of open /dev/dt nodes */
+SLIST_HEAD(, dt_softc) dtdev_list; /* [K] list of open /dev/dt nodes */
 
 /*
  * Probes are created during dt_attach() and never modified/freed during
@@ -104,7 +104,7 @@ unsigned intdt_nprobes; /* [I] 
# of p
 SIMPLEQ_HEAD(, dt_probe)   dt_probe_list;  /* [I] list of probes */
 
 struct rwlock  dt_lock = RWLOCK_INITIALIZER("dtlk");
-volatile uint32_t  dt_tracing = 0; /* [k] # of processes tracing */
+volatile uint32_t  dt_tracing = 0; /* [K] # of processes tracing */
 
 void   dtattach(struct device *, struct device *, void *);
 intdtopen(dev_t, int, int, struct proc *);
Index: dev/dt/dtvar.h
===
RCS file: /cvs/src/sys/dev/dt/dtvar.h,v
retrieving revision 1.3
diff -u -p -r1.3 dtvar.h
--- dev/dt/dtvar.h  28 Mar 2020 15:42:25 -  1.3
+++ dev/dt/dtvar.h  29 Jun 2020 18:47:30 -
@@ -159,14 +159,14 @@ int   dtioc_req_isvalid(struct dtioc_req 
  *
  *  Locks used to protect struct members in this file:
  * I   immutable after creation
- * k   kernel lock
- * k,s kernel lock for writting and SMR for reading
+ * K   kernel lock
+ * K,S kernel lock for writting and SMR for reading
  * m   per-pcb mutex
  * c   owned (read & modified) by a single CPU
  */
 struct dt_pcb {
-   SMR_SLIST_ENTRY(dt_pcb)  dp_pnext;  /* [k,s] next PCB per probe */
-   TAILQ_ENTRY(dt_pcb)  dp_snext;  /* [k] next PCB per softc */
+   SMR_SLIST_ENTRY(dt_pcb)  dp_pnext;  /* [K,S] next PCB per probe */
+   TAILQ_ENTRY(dt_pcb)  dp_snext;  /* [K] next PCB per softc */
 
/* Event states ring */
unsigned int dp_prod;   /* [m] read index */
@@ -203,18 +203,18 @@ void   dt_pcb_ring_consume(struct dt_pcb
  *
  *  Locks used to protect struct members in this file:
  * I   immutable after creation
- * k   kernel lock
- * d   dt_lock
- * d,s dt_lock for writting and SMR for reading
+ * K   kernel lock
+ * D   dt_lock
+ * D,S dt_lock for writting and SMR for reading
  */
 struct dt_probe {
-   SIMPLEQ_ENTRY(dt_probe)  dtp_next;  /* [k] global list of probes */
-   SMR_SLIST_HEAD(, dt_pcb) dtp_pcbs;  /* [d,s] list of enabled PCBs */
+   SIMPLEQ_ENTRY(dt_probe)  dtp_next;  /* [K] global list of probes */
+   SMR_SLIST_HEAD(, dt_pcb) dtp_pcbs;  /* [D,S] list of enabled PCBs */
struct dt_provider  *dtp_prov;  /* [I] its to provider */
const char  *dtp_func;  /* [I] probe function */
const char  *dtp_name;  /* [I] probe name */
uint32_t dtp_pbn;   /* [I] unique ID */
-   volatile uint32_tdtp_recording; /* [d] is it recording? */
+   volatile uint32_tdtp_recording; /* [D] is it recording? */
uint8_t  

Re: pipe: reduce number of allocations

2020-06-23 Thread Anton Lindqvist
On Tue, Jun 16, 2020 at 09:10:54PM +0200, Anton Lindqvist wrote:
> Hi,
> Instead of performing three distinct allocations per created pipe,
> reduce it to a single one. Not only should this be more performant, it
> also solves a kqueue related issue found by visa@ who also requested
> this change:
> 
> > If you attach an EVFILT_WRITE filter to a pipe fd, the knote gets added
> > to the peer's klist. This is a problem for kqueue  because if you close
> > the peer's fd, the knote is left in the list whose head is about to be
> > freed. knote_fdclose() is not able to clear the knote because it is not
> > registered with the peer's fd.
> 
> FreeBSD also takes a similar approach to pipe allocations.
> 
> Comments? OK?

This was backed out since it contained bug. Updated diff below in which
pipe_buffer_free() is called while holding the pipe lock in
pipe_destroy(). This prevents another thread from freeing the pipe_pair
structure while another thread is sleeping inside pipe_buffer_free().

Note that pipe_buffer_free() is also called from pipe_buffer_realloc().
The pipe is then either being created, i.e. we have exclusive access at
this point or the pipe lock is already acquired.

Comments? OK?

Index: kern/sys_pipe.c
===
RCS file: /cvs/src/sys/kern/sys_pipe.c,v
retrieving revision 1.122
diff -u -p -r1.122 sys_pipe.c
--- kern/sys_pipe.c 19 Jun 2020 02:08:48 -  1.122
+++ kern/sys_pipe.c 22 Jun 2020 19:23:56 -
@@ -49,6 +49,12 @@
 
 #include 
 
+struct pipe_pair {
+   struct pipe pp_wpipe;
+   struct pipe pp_rpipe;
+   struct rwlock pp_lock;
+};
+
 /*
  * interfaces to the outside world
  */
@@ -103,13 +109,12 @@ const struct filterops pipe_wfiltops = {
 unsigned int nbigpipe;
 static unsigned int amountpipekva;
 
-struct pool pipe_pool;
-struct pool pipe_lock_pool;
+struct pool pipe_pair_pool;
 
 intdopipe(struct proc *, int *, int);
 void   pipeselwakeup(struct pipe *);
 
-struct pipe *pipe_create(void);
+intpipe_create(struct pipe *);
 void   pipe_destroy(struct pipe *);
 intpipe_rundown(struct pipe *);
 struct pipe *pipe_peer(struct pipe *);
@@ -120,6 +125,8 @@ int pipe_iolock(struct pipe *);
 void   pipe_iounlock(struct pipe *);
 intpipe_iosleep(struct pipe *, const char *);
 
+struct pipe_pair *pipe_pair_create(void);
+
 /*
  * The pipe system call for the DTYPE_PIPE type of pipes
  */
@@ -153,33 +160,17 @@ dopipe(struct proc *p, int *ufds, int fl
 {
struct filedesc *fdp = p->p_fd;
struct file *rf, *wf;
+   struct pipe_pair *pp;
struct pipe *rpipe, *wpipe = NULL;
-   struct rwlock *lock;
int fds[2], cloexec, error;
 
cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
 
-   if ((rpipe = pipe_create()) == NULL) {
-   error = ENOMEM;
-   goto free1;
-   }
-
-   /*
-* One lock is used per pipe pair in order to obtain exclusive access to
-* the pipe pair.
-*/
-   lock = pool_get(_lock_pool, PR_WAITOK);
-   rw_init(lock, "pipelk");
-   rpipe->pipe_lock = lock;
-
-   if ((wpipe = pipe_create()) == NULL) {
-   error = ENOMEM;
-   goto free1;
-   }
-   wpipe->pipe_lock = lock;
-
-   rpipe->pipe_peer = wpipe;
-   wpipe->pipe_peer = rpipe;
+   pp = pipe_pair_create();
+   if (pp == NULL)
+   return (ENOMEM);
+   wpipe = >pp_wpipe;
+   rpipe = >pp_rpipe;
 
fdplock(fdp);
 
@@ -226,7 +217,6 @@ free3:
rpipe = NULL;
 free2:
fdpunlock(fdp);
-free1:
pipe_destroy(wpipe);
pipe_destroy(rpipe);
return (error);
@@ -272,19 +262,14 @@ pipe_buffer_realloc(struct pipe *cpipe, 
 /*
  * initialize and allocate VM and memory for pipe
  */
-struct pipe *
-pipe_create(void)
+int
+pipe_create(struct pipe *cpipe)
 {
-   struct pipe *cpipe;
int error;
 
-   cpipe = pool_get(_pool, PR_WAITOK | PR_ZERO);
-
error = pipe_buffer_realloc(cpipe, PIPE_SIZE);
-   if (error != 0) {
-   pool_put(_pool, cpipe);
-   return (NULL);
-   }
+   if (error != 0)
+   return (error);
 
sigio_init(>pipe_sigio);
 
@@ -292,7 +277,7 @@ pipe_create(void)
cpipe->pipe_atime = cpipe->pipe_ctime;
cpipe->pipe_mtime = cpipe->pipe_ctime;
 
-   return (cpipe);
+   return (0);
 }
 
 struct pipe *
@@ -834,7 +819,6 @@ void
 pipe_destroy(struct pipe *cpipe)
 {
struct pipe *ppipe;
-   struct rwlock *lock = NULL;
 
if (cpipe == NULL)
return;
@@ -862,20 +846,14 @@ pipe_destroy(struct pipe *cpipe)
ppipe->pipe_state |= PIPE_EOF;
wakeup(ppipe);
ppipe->pipe_peer = NULL;
-   } else {
-   /*
-

pipe: reduce number of allocations

2020-06-16 Thread Anton Lindqvist
Hi,
Instead of performing three distinct allocations per created pipe,
reduce it to a single one. Not only should this be more performant, it
also solves a kqueue related issue found by visa@ who also requested
this change:

> If you attach an EVFILT_WRITE filter to a pipe fd, the knote gets added
> to the peer's klist. This is a problem for kqueue  because if you close
> the peer's fd, the knote is left in the list whose head is about to be
> freed. knote_fdclose() is not able to clear the knote because it is not
> registered with the peer's fd.

FreeBSD also takes a similar approach to pipe allocations.

Comments? OK?

Index: kern/sys_pipe.c
===
RCS file: /cvs/src/sys/kern/sys_pipe.c,v
retrieving revision 1.120
diff -u -p -r1.120 sys_pipe.c
--- kern/sys_pipe.c 15 Jun 2020 15:29:40 -  1.120
+++ kern/sys_pipe.c 16 Jun 2020 19:07:49 -
@@ -49,6 +49,12 @@
 
 #include 
 
+struct pipe_pair {
+   struct pipe pp_wpipe;
+   struct pipe pp_rpipe;
+   struct rwlock pp_lock;
+};
+
 /*
  * interfaces to the outside world
  */
@@ -103,13 +109,12 @@ const struct filterops pipe_wfiltops = {
 unsigned int nbigpipe;
 static unsigned int amountpipekva;
 
-struct pool pipe_pool;
-struct pool pipe_lock_pool;
+struct pool pipe_pair_pool;
 
 intdopipe(struct proc *, int *, int);
 void   pipeselwakeup(struct pipe *);
 
-struct pipe *pipe_create(void);
+intpipe_create(struct pipe *);
 void   pipe_destroy(struct pipe *);
 intpipe_rundown(struct pipe *);
 struct pipe *pipe_peer(struct pipe *);
@@ -120,6 +125,8 @@ int pipe_iolock(struct pipe *);
 void   pipe_iounlock(struct pipe *);
 intpipe_iosleep(struct pipe *, const char *);
 
+struct pipe_pair *pipe_pair_create(void);
+
 /*
  * The pipe system call for the DTYPE_PIPE type of pipes
  */
@@ -153,33 +160,17 @@ dopipe(struct proc *p, int *ufds, int fl
 {
struct filedesc *fdp = p->p_fd;
struct file *rf, *wf;
+   struct pipe_pair *pp;
struct pipe *rpipe, *wpipe = NULL;
-   struct rwlock *lock;
int fds[2], cloexec, error;
 
cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
 
-   if ((rpipe = pipe_create()) == NULL) {
-   error = ENOMEM;
-   goto free1;
-   }
-
-   /*
-* One lock is used per pipe pair in order to obtain exclusive access to
-* the pipe pair.
-*/
-   lock = pool_get(_lock_pool, PR_WAITOK);
-   rw_init(lock, "pipelk");
-   rpipe->pipe_lock = lock;
-
-   if ((wpipe = pipe_create()) == NULL) {
-   error = ENOMEM;
-   goto free1;
-   }
-   wpipe->pipe_lock = lock;
-
-   rpipe->pipe_peer = wpipe;
-   wpipe->pipe_peer = rpipe;
+   pp = pipe_pair_create();
+   if (pp == NULL)
+   return (ENOMEM);
+   wpipe = >pp_wpipe;
+   rpipe = >pp_rpipe;
 
fdplock(fdp);
 
@@ -226,7 +217,6 @@ free3:
rpipe = NULL;
 free2:
fdpunlock(fdp);
-free1:
pipe_destroy(wpipe);
pipe_destroy(rpipe);
return (error);
@@ -272,19 +262,14 @@ pipe_buffer_realloc(struct pipe *cpipe, 
 /*
  * initialize and allocate VM and memory for pipe
  */
-struct pipe *
-pipe_create(void)
+int
+pipe_create(struct pipe *cpipe)
 {
-   struct pipe *cpipe;
int error;
 
-   cpipe = pool_get(_pool, PR_WAITOK | PR_ZERO);
-
error = pipe_buffer_realloc(cpipe, PIPE_SIZE);
-   if (error != 0) {
-   pool_put(_pool, cpipe);
-   return (NULL);
-   }
+   if (error != 0)
+   return (error);
 
sigio_init(>pipe_sigio);
 
@@ -292,7 +277,7 @@ pipe_create(void)
cpipe->pipe_atime = cpipe->pipe_ctime;
cpipe->pipe_mtime = cpipe->pipe_ctime;
 
-   return (cpipe);
+   return (0);
 }
 
 struct pipe *
@@ -834,7 +819,6 @@ void
 pipe_destroy(struct pipe *cpipe)
 {
struct pipe *ppipe;
-   struct rwlock *lock = NULL;
 
if (cpipe == NULL)
return;
@@ -862,20 +846,13 @@ pipe_destroy(struct pipe *cpipe)
ppipe->pipe_state |= PIPE_EOF;
wakeup(ppipe);
ppipe->pipe_peer = NULL;
-   } else {
-   /*
-* Peer already gone. This is last reference to the pipe lock
-* and it must therefore be freed below.
-*/
-   lock = cpipe->pipe_lock;
}
 
rw_exit_write(cpipe->pipe_lock);
 
pipe_buffer_free(cpipe);
-   if (lock != NULL)
-   pool_put(_lock_pool, lock);
-   pool_put(_pool, cpipe);
+   if (ppipe == NULL)
+   pool_put(_pair_pool, cpipe->pipe_pair);
 }
 
 /*
@@ -1008,8 +985,33 @@ filt_pipewrite(struct knote *kn, long hi
 void
 pipe_init(void)
 {
-   pool_init(_pool, sizeof(struct pipe), 0, IPL_MPFLOOR, PR_WAITOK,
-   "pipepl", NULL);
-   pool_init(_lock_pool, sizeof(struct rwlock), 0, IPL_MPFLOOR,

Re: Call FRELE() without fdplock in dup*(2)

2020-06-10 Thread Anton Lindqvist
On Wed, Jun 10, 2020 at 02:34:00PM +, Visa Hankala wrote:
> A while ago, finishdup() was changed to release fdplock before calling
> closef() to avoid potential lock order problems in the file close path.
> However, the dup* code can still invoke that path with fdplock held
> through FRELE(). That is fixed by the diff below.
> 
> (In principle, the FRELE(fp, p) could be eliminated by getting fp while
> the file descriptor table is locked. As long as the lock is held, other
> threads are unable to close the file descriptor and hence the temporary
> file reference is unnecessary.)
> 
> OK?

ok anton@



ddb(4): missing tags

2020-05-17 Thread Anton Lindqvist
Hi,
The ddb(4) manual documents a couple of commands which can be
abbreviated. The diff below adds explicit tags for such commands which
in turn makes it possible to jump to for instance `examine' from within
your $PAGER.

Comments? OK?

Index: ddb.4
===
RCS file: /cvs/src/share/man/man4/ddb.4,v
retrieving revision 1.96
diff -u -p -r1.96 ddb.4
--- ddb.4   14 May 2020 06:58:54 -  1.96
+++ ddb.4   17 May 2020 08:54:18 -
@@ -202,6 +202,7 @@ are displayed and no other action is per
 .It Ic help
 List the available commands.
 .\" 
+.Tg examine
 .It Xo
 .Oo Ic e Oc Ns
 .Ic x Ns Op Ic amine
@@ -275,6 +276,7 @@ is set to the
 .Ar addr
 plus the size of the data examined.
 .\" 
+.Tg print
 .It Xo
 .Ic p Ns Op Ic rint
 .Op Cm /axzodurc
@@ -301,6 +303,7 @@ will print something like this:
 xx
 .Ed
 .\" 
+.Tg pprint
 .It Xo
 .Ic pp Ns Op Ic rint
 .Op Ar addr
@@ -316,6 +319,7 @@ as part of building a new kernel.
 .\" .Op Ar addr
 .\" .Ar expr Op expr ...
 .\" .Xc
+.Tg write
 .It Xo
 .Ic w Ns Op Ic rite
 .Op Cm /bhl
@@ -394,6 +398,7 @@ allows the breakpoint to be silently hit
 times before stopping at the
 break point.
 .\" 
+.Tg delete
 .It Xo
 .Ic d Ns Op Ic elete
 .Op Ar addr
@@ -405,6 +410,7 @@ command.
 .\" .It Xo Ic s Ns Op Cm /p
 .\" .Op Ic \&, Ns Ar count
 .\" .Xc
+.Tg step
 .It Xo
 .Ic s Ns Op Ic tep
 .Op Cm /p
@@ -437,6 +443,7 @@ Parentheses may be omitted if the functi
 The number of arguments is currently limited to 10.
 .\" 
 .\" .It Ic c Ns Op Cm /c
+.Tg continue
 .It Xo
 .Ic c Ns Op Ic ontinue
 .Op Cm /c
@@ -949,6 +956,7 @@ command.
 A synonym for
 .Ic show all procs .
 .\" 
+.Tg machine
 .It Xo
 .Ic mac Ns Op Ic hine
 .Ar subcommand Op Ar args ...



flock unlock

2020-03-13 Thread Anton Lindqvist
Hi,
After reading the flock(2) code I cannot spot anything preventing it
from being unlocked. This is all made possible by the recent MP-safe
effort including atomic file flags and posix file locks.

I've been running with this for a week by now. However, testing is much
appreciated. Remember to run `make -C sys/kern syscalls' after applying
the diff.

I'm not rushing this one as fcntl(2) was recently unlocked. Will commit
later next week unless I hear objections.

Comments? OK?

Index: kern/syscalls.master
===
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.206
diff -u -p -r1.206 syscalls.master
--- kern/syscalls.master10 Mar 2020 19:20:14 -  1.206
+++ kern/syscalls.master13 Mar 2020 10:13:03 -
@@ -260,7 +260,7 @@
 128STD { int sys_rename(const char *from, const char *to); }
 129OBSOL   otruncate
 130OBSOL   oftruncate
-131STD { int sys_flock(int fd, int how); }
+131STD NOLOCK  { int sys_flock(int fd, int how); }
 132STD { int sys_mkfifo(const char *path, mode_t mode); }
 133STD NOLOCK  { ssize_t sys_sendto(int s, const void *buf, \
size_t len, int flags, const struct sockaddr *to, \



atomic f_iflags

2020-03-10 Thread Anton Lindqvist
Hi,
In order to unlock flock(2), make writes to the f_iflags field of struct
file atomic; similar to recent changes to both struct file and process.
This also gets rid of the last kernel lock protected field in the scope
of struct file.

Comments? OK?

Index: kern/kern_descrip.c
===
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.200
diff -u -p -r1.200 kern_descrip.c
--- kern/kern_descrip.c 26 Feb 2020 13:54:52 -  1.200
+++ kern/kern_descrip.c 5 Mar 2020 11:51:28 -
@@ -707,7 +707,7 @@ fdinsert(struct filedesc *fdp, int fd, i
 
mtx_enter();
if ((fp->f_iflags & FIF_INSERTED) == 0) {
-   fp->f_iflags |= FIF_INSERTED;
+   atomic_setbits_int(>f_iflags, FIF_INSERTED);
if ((fq = fdp->fd_ofiles[0]) != NULL) {
LIST_INSERT_AFTER(fq, fp, f_list);
} else {
@@ -1317,7 +1317,7 @@ sys_flock(struct proc *p, void *v, regis
lf.l_len = 0;
if (how & LOCK_UN) {
lf.l_type = F_UNLCK;
-   fp->f_iflags &= ~FIF_HASLOCK;
+   atomic_clearbits_int(>f_iflags, FIF_HASLOCK);
error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, , F_FLOCK);
goto out;
}
@@ -1329,7 +1329,7 @@ sys_flock(struct proc *p, void *v, regis
error = EINVAL;
goto out;
}
-   fp->f_iflags |= FIF_HASLOCK;
+   atomic_setbits_int(>f_iflags, FIF_HASLOCK);
if (how & LOCK_NB)
error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, , F_FLOCK);
else
Index: kern/vfs_syscalls.c
===
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.342
diff -u -p -r1.342 vfs_syscalls.c
--- kern/vfs_syscalls.c 30 Jan 2020 15:36:11 -  1.342
+++ kern/vfs_syscalls.c 5 Mar 2020 11:51:28 -
@@ -1188,7 +1188,7 @@ doopenat(struct proc *p, int fd, const c
goto out;
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-   fp->f_iflags |= FIF_HASLOCK;
+   atomic_setbits_int(>f_iflags, FIF_HASLOCK);
}
if (localtrunc) {
if ((fp->f_flag & FWRITE) == 0)
@@ -1457,7 +1457,7 @@ sys_fhopen(struct proc *p, void *v, regi
goto bad;
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-   fp->f_iflags |= FIF_HASLOCK;
+   atomic_setbits_int(>f_iflags, FIF_HASLOCK);
}
VOP_UNLOCK(vp);
*retval = indx;
Index: sys/file.h
===
RCS file: /cvs/src/sys/sys/file.h,v
retrieving revision 1.60
diff -u -p -r1.60 file.h
--- sys/file.h  1 Feb 2020 08:57:27 -   1.60
+++ sys/file.h  5 Mar 2020 11:51:28 -
@@ -75,7 +75,6 @@ structfileops {
  * a   atomic operations
  * f   per file `f_mtx'
  * v   vnode lock
- * k   kernel lock
  */
 struct file {
LIST_ENTRY(file) f_list;/* [F] list of active files */
@@ -86,7 +85,7 @@ struct file {
 #defineDTYPE_PIPE  3   /* pipe */
 #defineDTYPE_KQUEUE4   /* event queue */
 #defineDTYPE_DMABUF5   /* DMA buffer (for DRM) */
-   int f_iflags;   /* [k] internal flags */
+   u_int   f_iflags;   /* [a] internal flags */
int f_type; /* [I] descriptor type */
u_int   f_count;/* [a] reference count */
struct  ucred *f_cred;  /* [I] credentials associated with descriptor */
Index: sys/sysctl.h
===
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.204
diff -u -p -r1.204 sysctl.h
--- sys/sysctl.h16 Feb 2020 07:55:30 -  1.204
+++ sys/sysctl.h5 Mar 2020 11:51:28 -
@@ -735,7 +735,7 @@ do {
\
 struct kinfo_file {
uint64_tf_fileaddr; /* PTR: address of struct file */
uint32_tf_flag; /* UINT: flags (see fcntl.h) */
-   uint32_tf_iflags;   /* INT: internal flags */
+   uint32_tf_iflags;   /* UINT: internal flags */
uint32_tf_type; /* INT: descriptor type */
uint32_tf_count;/* UINT: reference count */
uint32_tf_msgcount; /* UINT: references from msg queue */



  1   2   3   >