Author: mav
Date: Thu Mar 24 08:56:12 2011
New Revision: 219951
URL: http://svn.freebsd.org/changeset/base/219951

Log:
  MFgraid/head r218174:
  Add simple in-kernel API for controlling leds.

Modified:
  head/sys/dev/led/led.c
  head/sys/dev/led/led.h

Modified: head/sys/dev/led/led.c
==============================================================================
--- head/sys/dev/led/led.c      Thu Mar 24 08:37:48 2011        (r219950)
+++ head/sys/dev/led/led.c      Thu Mar 24 08:56:12 2011        (r219951)
@@ -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: head/sys/dev/led/led.h
==============================================================================
--- head/sys/dev/led/led.h      Thu Mar 24 08:37:48 2011        (r219950)
+++ head/sys/dev/led/led.h      Thu Mar 24 08:56:12 2011        (r219951)
@@ -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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to