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>