Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Jun 2011 06:19:24 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r223175 - stable/8/sys/dev/led
Message-ID:  <201106170619.p5H6JOgd063835@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Fri Jun 17 06:19:23 2011
New Revision: 223175
URL: http://svn.freebsd.org/changeset/base/223175

Log:
  MFC r219951:
  Add simple in-kernel API for controlling leds.

Modified:
  stable/8/sys/dev/led/led.c
  stable/8/sys/dev/led/led.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/dev/led/led.c
==============================================================================
--- stable/8/sys/dev/led/led.c	Fri Jun 17 06:17:45 2011	(r223174)
+++ stable/8/sys/dev/led/led.c	Fri Jun 17 06:19:23 2011	(r223175)
@@ -26,6 +26,7 @@ __FBSDID("$FreeBSD$");
 
 struct ledsc {
 	LIST_ENTRY(ledsc)	list;
+	char			*name;
 	void			*private;
 	int			unit;
 	led_t			*func;
@@ -83,71 +84,43 @@ led_timeout(void *p)
 }
 
 static int
-led_state(struct cdev *dev, struct sbuf *sb, int state)
+led_state(struct ledsc *sc, struct sbuf **sb, int state)
 {
 	struct sbuf *sb2 = NULL;
-	struct ledsc *sc;
 
-	mtx_lock(&led_mtx);
-	sc = dev->si_drv1;
-	if (sc != NULL) {
-		sb2 = sc->spec;
-		sc->spec = sb;
-		if (sb != NULL) {
-			sc->str = sbuf_data(sb);
-			sc->ptr = sc->str;
-		} else {
-			sc->str = NULL;
-			sc->ptr = NULL;
-			sc->func(sc->private, state);
-		}
-		sc->count = 0;
+	sb2 = sc->spec;
+	sc->spec = *sb;
+	if (*sb != NULL) {
+		sc->str = sbuf_data(*sb);
+		sc->ptr = sc->str;
+	} else {
+		sc->str = NULL;
+		sc->ptr = NULL;
+		sc->func(sc->private, state);
 	}
-	mtx_unlock(&led_mtx);
-	if (sb2 != NULL)
-		sbuf_delete(sb2);
-	if (sc == NULL)
-		return (ENXIO);
+	sc->count = 0;
+	*sb = sb2;
 	return(0);
 }
 
 static int
-led_write(struct cdev *dev, struct uio *uio, int ioflag)
+led_parse(const char *s, struct sbuf **sb, int *state)
 {
-	int error;
-	char *s, *s2;
-	struct sbuf *sb = NULL;
-	int i;
-
-	if (dev->si_drv1 == NULL)
-		return (ENXIO);
-
-	if (uio->uio_resid > 512)
-		return (EINVAL);
-	s2 = s = malloc(uio->uio_resid + 1, M_DEVBUF, M_WAITOK);
-	s[uio->uio_resid] = '\0';
-	error = uiomove(s, uio->uio_resid, uio);
-	if (error) {
-		free(s2, M_DEVBUF);
-		return (error);
-	}
+	int i, error;
 
 	/*
 	 * Handle "on" and "off" immediately so people can flash really
 	 * fast from userland if they want to
 	 */
 	if (*s == '0' || *s == '1') {
-		error = led_state(dev, NULL, *s & 1);
-		free(s2, M_DEVBUF);
-		return(error);
+		*state = *s & 1;
+		return (0);
 	}
 
-	sb = sbuf_new_auto();
-	if (sb == NULL) {
-		free(s2, M_DEVBUF);
+	*state = 0;
+	*sb = sbuf_new_auto();
+	if (*sb == NULL)
 		return (ENOMEM);
-	}
-		
 	switch(s[0]) {
 		/*
 		 * Flash, default is 100msec/100msec.
@@ -158,7 +131,7 @@ led_write(struct cdev *dev, struct uio *
 				i = s[1] - '1';
 			else
 				i = 0;
-			sbuf_printf(sb, "%c%c", 'A' + i, 'a' + i);
+			sbuf_printf(*sb, "%c%c", 'A' + i, 'a' + i);
 			break;
 		/*
 		 * Digits, flashes out numbers.
@@ -172,10 +145,10 @@ led_write(struct cdev *dev, struct uio *
 				if (i == 0)
 					i = 10;
 				for (; i > 1; i--) 
-					sbuf_cat(sb, "Aa");
-				sbuf_cat(sb, "Aj");
+					sbuf_cat(*sb, "Aa");
+				sbuf_cat(*sb, "Aj");
 			}
-			sbuf_cat(sb, "jj");
+			sbuf_cat(*sb, "jj");
 			break;
 		/*
 		 * String, roll your own.
@@ -190,7 +163,7 @@ led_write(struct cdev *dev, struct uio *
 				    (*s >= 'A' && *s <= 'J') ||
 				    *s == 'U' || *s <= 'u' ||
 					*s == '.')
-					sbuf_bcat(sb, s, 1);
+					sbuf_bcat(*sb, s, 1);
 			}
 			break;
 		/*
@@ -205,29 +178,82 @@ led_write(struct cdev *dev, struct uio *
 		case 'm':
 			for(s++; *s; s++) {
 				if (*s == '.')
-					sbuf_cat(sb, "aA");
+					sbuf_cat(*sb, "aA");
 				else if (*s == '-')
-					sbuf_cat(sb, "aC");
+					sbuf_cat(*sb, "aC");
 				else if (*s == ' ')
-					sbuf_cat(sb, "b");
+					sbuf_cat(*sb, "b");
 				else if (*s == '\n')
-					sbuf_cat(sb, "d");
+					sbuf_cat(*sb, "d");
 			}
-			sbuf_cat(sb, "j");
+			sbuf_cat(*sb, "j");
 			break;
 		default:
-			sbuf_delete(sb);
-			free(s2, M_DEVBUF);
+			sbuf_delete(*sb);
 			return (EINVAL);
 	}
-	error = sbuf_finish(sb);
-	free(s2, M_DEVBUF);
-	if (error != 0 || sbuf_len(sb) == 0) {
-		sbuf_delete(sb);
+	error = sbuf_finish(*sb);
+	if (error != 0 || sbuf_len(*sb) == 0) {
+		*sb = NULL;
+		return (error);
+	}
+	return (0);
+}
+
+static int
+led_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+	struct ledsc	*sc;
+	char *s;
+	struct sbuf *sb = NULL;
+	int error, state = 0;
+
+	if (uio->uio_resid > 512)
+		return (EINVAL);
+	s = malloc(uio->uio_resid + 1, M_DEVBUF, M_WAITOK);
+	s[uio->uio_resid] = '\0';
+	error = uiomove(s, uio->uio_resid, uio);
+	if (error) {
+		free(s, M_DEVBUF);
 		return (error);
 	}
+	error = led_parse(s, &sb, &state);
+	free(s, M_DEVBUF);
+	if (error)
+		return (error);
+	mtx_lock(&led_mtx);
+	sc = dev->si_drv1;
+	if (sc != NULL)
+		error = led_state(sc, &sb, state);
+	mtx_unlock(&led_mtx);
+	if (sb != NULL)
+		sbuf_delete(sb);
+	return (error);
+}
 
-	return (led_state(dev, sb, 0));
+int
+led_set(char const *name, char const *cmd)
+{
+	struct ledsc	*sc;
+	struct sbuf *sb = NULL;
+	int error, state = 0;
+
+	error = led_parse(cmd, &sb, &state);
+	if (error)
+		return (error);
+	mtx_lock(&led_mtx);
+	LIST_FOREACH(sc, &led_list, list) {
+		if (strcmp(sc->name, name) == 0)
+			break;
+	}
+	if (sc != NULL)
+		error = led_state(sc, &sb, state);
+	else
+		error = ENOENT;
+	mtx_unlock(&led_mtx);
+	if (sb != NULL)
+		sbuf_delete(sb);
+	return (0);
 }
 
 static struct cdevsw led_cdevsw = {
@@ -250,6 +276,7 @@ led_create_state(led_t *func, void *priv
 	sc = malloc(sizeof *sc, M_LED, M_WAITOK | M_ZERO);
 
 	sx_xlock(&led_sx);
+	sc->name = strdup(name, M_LED);
 	sc->unit = alloc_unr(led_unit);
 	sc->private = priv;
 	sc->func = func;
@@ -287,6 +314,7 @@ led_destroy(struct cdev *dev)
 	destroy_dev(dev);
 	if (sc->spec != NULL)
 		sbuf_delete(sc->spec);
+	free(sc->name, M_LED);
 	free(sc, M_LED);
 	sx_xunlock(&led_sx);
 }

Modified: stable/8/sys/dev/led/led.h
==============================================================================
--- stable/8/sys/dev/led/led.h	Fri Jun 17 06:17:45 2011	(r223174)
+++ stable/8/sys/dev/led/led.h	Fri Jun 17 06:19:23 2011	(r223175)
@@ -18,4 +18,6 @@ struct cdev *led_create_state(led_t *, v
 struct cdev *led_create(led_t *, void *, char const *);
 void	led_destroy(struct cdev *);
 
+int	led_set(char const *, char const *);
+
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106170619.p5H6JOgd063835>