Hi,

I tried to add kqueue I/F to kbd.c. I attached patch.
What do you think about my patch?

Best regards,
 Kohji Okuno
diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c
index 8036762..df000ab 100644
--- a/sys/dev/kbd/kbd.c
+++ b/sys/dev/kbd/kbd.c
@@ -59,6 +59,9 @@ typedef struct genkbd_softc {
 	char		gkb_q[KB_QSIZE];		/* input queue */
 	unsigned int	gkb_q_start;
 	unsigned int	gkb_q_length;
+#if 1
+	unsigned int	gkb_index;
+#endif
 } genkbd_softc_t;
 
 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
@@ -472,6 +475,9 @@ static d_read_t		genkbdread;
 static d_write_t	genkbdwrite;
 static d_ioctl_t	genkbdioctl;
 static d_poll_t		genkbdpoll;
+#if 1
+static d_kqfilter_t	genkbdkqfilter;
+#endif
 
 
 static struct cdevsw kbd_cdevsw = {
@@ -483,6 +489,9 @@ static struct cdevsw kbd_cdevsw = {
 	.d_write =	genkbdwrite,
 	.d_ioctl =	genkbdioctl,
 	.d_poll =	genkbdpoll,
+#if 1
+	.d_kqfilter =	genkbdkqfilter,
+#endif
 	.d_name =	"kbd",
 };
 
@@ -500,6 +509,13 @@ kbd_attach(keyboard_t *kbd)
 	make_dev_alias(kbd->kb_dev, "kbd%r", kbd->kb_index);
 	kbd->kb_dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
 	    M_WAITOK | M_ZERO);
+#if 1
+	{
+		genkbd_softc_t *sc = kbd->kb_dev->si_drv1;
+		sc->gkb_index = KBD_INDEX(kbd->kb_dev);
+		knlist_init_mtx(&sc->gkb_rsel.si_note, NULL);
+	}
+#endif
 	printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
 	return (0);
 }
@@ -697,6 +713,73 @@ genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *
 	return (error);
 }
 
+#if 1
+static void
+genkbd_kqops_detach(struct knote *kn)
+{
+	genkbd_softc_t *sc;
+	sc = kn->kn_hook;
+	knlist_remove(&sc->gkb_rsel.si_note, kn, 0);
+}
+
+static int
+genkbd_kqops_event(struct knote *kn, long hint)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+
+	sc = kn->kn_hook;
+	kbd = kbd_get_keyboard(sc->gkb_index);
+
+	if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		return 1;	/* the keyboard has gone */
+	}
+	else {
+		if (sc->gkb_q_length > 0)
+			return 1;
+		else
+			return 0;
+	}
+
+}
+static struct filterops genkbd_kqops =
+{
+	.f_isfd		= 1,
+	.f_attach	= NULL,
+	.f_detach	= genkbd_kqops_detach,
+	.f_event	= genkbd_kqops_event,
+};
+static int
+genkbdkqfilter(struct cdev *dev, struct knote *kn)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+	int error = 0;
+	int s;
+
+	s = spltty();
+	sc = dev->si_drv1;
+	kbd = kbd_get_keyboard(KBD_INDEX(dev));
+	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		error = EIO;
+	}
+	else  {
+		switch (kn->kn_filter) {
+		case EVFILT_READ:
+			kn->kn_fop = &genkbd_kqops;
+			kn->kn_hook = (void *)sc;
+			knlist_add(&sc->gkb_rsel.si_note, kn, 0);
+			break;
+		default:
+			error = EOPNOTSUPP;
+			break;
+		}
+	}
+	splx(s);
+	return (error);
+}
+#endif
+
 static int
 genkbdpoll(struct cdev *dev, int events, struct thread *td)
 {
@@ -744,6 +827,9 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(&sc->gkb_rsel, PZERO);
+#if 1
+		knlist_clear(&sc->gkb_rsel.si_note, 0);
+#endif
 		return (0);
 	default:
 		return (EINVAL);
@@ -814,6 +900,9 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(&sc->gkb_rsel, PZERO);
+#if 1
+		KNOTE_UNLOCKED(&sc->gkb_rsel.si_note, 0);
+#endif
 	}
 
 	return (0);
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to