From: Brajesh Dave <[EMAIL PROTECTED]>

See https://dev.laptop.org/ticket/2384#comment:4

Requires firmware version 5.110.19.p0 or newer, available here:
http://dev.laptop.org/pub/firmware/libertas/

Signed-off-by: Ashish Shukla <[EMAIL PROTECTED]>
Signed-off-by: Javier Cardona <[EMAIL PROTECTED]>
---
 drivers/net/wireless/libertas/README    |   57 ++++++++++++++++++++
 drivers/net/wireless/libertas/hostcmd.h |    2 +-
 drivers/net/wireless/libertas/ioctl.c   |   89 +++++++++++++++++++++++++++++++
 drivers/net/wireless/libertas/types.h   |   14 +++++
 drivers/net/wireless/libertas/wext.c    |    1 +
 drivers/net/wireless/libertas/wext.h    |    3 +-
 6 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/libertas/README 
b/drivers/net/wireless/libertas/README
index 73f1893..9f2b029 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -163,6 +163,63 @@ bcn_control
                   Enable beacon with beacon interval 500ms.
                
 
+ledbhv
+      Command iwpriv mshX ledbhv can be used to change default LEDs behaviors.
+      A given LED behavior can be on, off or blinking. The duty/cycle can be 
set
+      when behavior is programmed as blinking.
+
+      Usage:
+
+        1. To get default LED behavior
+           iwpriv mshX ledbhv <firmware state>
+
+        2. To set or change default LED behavior
+           iwpriv mshX ledbhv <firmware state> <lednum> <behavior> <arg>
+
+        firmware state: The following are some of the relevant states.
+          00: disconnected 
+          01: firmware is scanning
+          02: firmware is connected and awake
+          03: firmware is sleeping
+          04: connected deep sleep
+          06: firmware disconnected link lost 
+          07: firmware disconnected disassociated
+          09: data transfer while firmware is associated and not scanning. 
+              If firmware is already in this state, LED behavior does not 
change 
+              on this data transfer.
+          10: firmware idle, not scanning, not disconnected or disassociated.
+
+        lednum: 1 or 2 for first and second LED.
+  
+        behavior: 0 for steady ON, 1 - steady off and 2- blinking.
+
+        arg: It is used when behavior is 2 to set duty and cycle. It is 
defined as 
+             (duty << 4 | cycle). Here duty could be 0..4 and cycle 0..5 for 
34, 
+             74, 149, 298, 596, 1192 ms respectively.
+
+      Examples:
+
+       1. To get default behavior for scan
+          iwpriv mshX ledbhv 1
+
+       2. To get default behavior while data transfer
+          iwpriv mshX ledbhv 9      
+ 
+       3. To turn off LED 2
+          iwpriv mshX ledbhv 2 2 1 0
+          iwpriv mshX ledbhv 10 2 1 0
+
+       4. To enable LED 2 and blink LED 1 while data transfer.
+          iwpriv mshX ledbhv 9 2 0 0
+          iwpriv mshX ledbhv 9 1 2 4
+
+       5. To change duty cycle of LED 2 during data transfer
+          iwpriv mshX ledbhv 9 2 2 36
+
+       6. To turn ON LED 2 when firmware is disassociated/disconnected.
+          iwpriv mshX ledbhv 0 2 0 0
+       
+
 fwt_add
        This command is used to insert an entry into the FWT table. The list of
        parameters must follow the following structure:
diff --git a/drivers/net/wireless/libertas/hostcmd.h 
b/drivers/net/wireless/libertas/hostcmd.h
index 9c1b560..45a6108 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -546,7 +546,7 @@ struct cmd_ds_802_11_tpc_cfg {
 struct cmd_ds_802_11_led_ctrl {
        __le16 action;
        __le16 numled;
-       u8 data[256];
+       u8 data[288];
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_pwr_cfg {
diff --git a/drivers/net/wireless/libertas/ioctl.c 
b/drivers/net/wireless/libertas/ioctl.c
index 8648e68..3ededab 100644
--- a/drivers/net/wireless/libertas/ioctl.c
+++ b/drivers/net/wireless/libertas/ioctl.c
@@ -1000,6 +1000,92 @@ out:
 }
 
 
+static int libertas_led_bhv_ioctl(wlan_private * priv, struct ifreq *req)
+{
+       struct iwreq *wrq = (struct iwreq *)req;
+       int i, ret = 0;
+       int data[MAX_LEDS*4];
+       int firmwarestate = 0;
+       struct cmd_ds_802_11_led_ctrl ctrl;
+       struct mrvlietypes_ledbhv *bhv = (struct mrvlietypes_ledbhv *) 
ctrl.data;
+       int len = wrq->u.data.length;
+
+       if ((len > MAX_LEDS * 4) ||(len == 0)  )
+               return -ENOTSUPP;
+
+       memset(&ctrl, 0, sizeof(ctrl));
+       if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * len)) {
+                       lbs_deb_ioctl("Copy from user failed\n");
+                       ret = -EFAULT;
+                       goto out;
+       }
+       if (len == 1) {
+               ctrl.action = cpu_to_le16(CMD_ACT_GET);
+               firmwarestate = data[0];
+       } else {
+               
+               if (len % 4 != 0 )
+                       return -ENOTSUPP;
+
+               bhv->header.type = cpu_to_le16(TLV_TYPE_LEDBEHAVIOR);
+               bhv->header.len = len;
+               ctrl.action = cpu_to_le16(CMD_ACT_SET);
+               ctrl.numled = cpu_to_le16(0);
+               for (i = 0; i < len; i += 4) {
+                       bhv->ledbhv[i / 4].firmwarestate = data[i];
+                       bhv->ledbhv[i / 4].led = data[i + 1];
+                       bhv->ledbhv[i / 4].ledstate = data[i + 2];
+                       bhv->ledbhv[i / 4].ledarg = data[i + 3];
+               }
+       }
+
+       ret = libertas_prepare_and_send_command(priv, CMD_802_11_LED_GPIO_CTRL,
+                       0, CMD_OPTION_WAITFORRSP, 0, (void *)&ctrl);
+       if (ret) {
+               lbs_deb_ioctl("Error doing LED GPIO control: %d\n", ret);
+               goto out;
+       }
+
+       /* Get LED behavior IE, we have received gpio control as well when len 
+          is equal to 1. */
+       if (len ==1 ) {
+               bhv = (struct mrvlietypes_ledbhv *) 
+                 ((unsigned char *)bhv->ledbhv + bhv->header.len);
+               i = 0;
+               while ( i < (MAX_LEDS*4) &&
+                 (bhv->header.type != MRVL_TERMINATE_TLV_ID) ) {
+                       if (bhv->ledbhv[0].firmwarestate == firmwarestate) {
+                               data[i++] = bhv->ledbhv[0].firmwarestate;
+                               data[i++] = bhv->ledbhv[0].led;
+                               data[i++] = bhv->ledbhv[0].ledstate;
+                               data[i++] = bhv->ledbhv[0].ledarg;
+                       }
+                       bhv++;
+               }
+               len = i;
+       } else {
+               for (i = 0; i < bhv->header.len; i += 4) {
+                       data[i] = bhv->ledbhv[i / 4].firmwarestate;
+                       data[i + 1] = bhv->ledbhv[i / 4].led;
+                       data[i + 2] = bhv->ledbhv[i / 4].ledstate;
+                       data[i + 3] = bhv->ledbhv[i / 4].ledarg;
+               }
+               len = bhv->header.len;
+       }
+
+       if (copy_to_user(wrq->u.data.pointer, data,
+                        sizeof(int) * len)) {
+               lbs_deb_ioctl("Copy to user failed\n");
+               ret = -EFAULT;
+               goto out;
+       }
+
+       wrq->u.data.length = len;
+
+out:
+       return ret;
+}
+
 /**
  *  @brief ioctl function - entry point
  *
@@ -1145,6 +1231,9 @@ int libertas_do_ioctl(struct net_device *dev, struct 
ifreq *req, int cmd)
                case LIBERTAS_BCN_CTRL:
                        ret = libertas_bcn_ioctl(priv,wrq);
                        break;
+               case LIBERTAS_LED_BEHAVIOR_CTRL:
+                       ret = libertas_led_bhv_ioctl(priv, req);
+                       break;
                }
                break;
 
diff --git a/drivers/net/wireless/libertas/types.h 
b/drivers/net/wireless/libertas/types.h
index a43a5f6..f3ae983 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -250,4 +250,18 @@ struct mrvlietypes_ledgpio {
        struct led_pin ledpin[1];
 } __attribute__ ((packed));
 
+struct led_bhv {
+    u8  firmwarestate;
+    u8  led;
+    u8  ledstate;
+    u8  ledarg;
+} __attribute__ ((packed));
+
+
+struct mrvlietypes_ledbhv {
+       struct mrvlietypesheader header;
+       struct led_bhv ledbhv[1];
+} __attribute__ ((packed));
+
+
 #endif                         /* _WLAN_TYPES_ */
diff --git a/drivers/net/wireless/libertas/wext.c 
b/drivers/net/wireless/libertas/wext.c
index 1c8128d..11f9389 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -862,6 +862,7 @@ static const struct iw_priv_args wlan_private_args[] = {
        { LIBERTAS_SET_GET_SIXTEEN_INT, INT16_PARAM, INT16_PARAM, ""},
            { LIBERTAS_LED_GPIO_CTRL, INT16_PARAM, INT16_PARAM, "ledgpio"},
            { LIBERTAS_BCN_CTRL, INT16_PARAM, INT16_PARAM, "bcn_control"},
+           { LIBERTAS_LED_BEHAVIOR_CTRL, INT16_PARAM, INT16_PARAM, "ledbhv"},
 };
 
 static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
diff --git a/drivers/net/wireless/libertas/wext.h 
b/drivers/net/wireless/libertas/wext.h
index eb155aa..e93853b 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -48,7 +48,8 @@
 
 #define LIBERTAS_SET_GET_SIXTEEN_INT           (SIOCIWFIRSTPRIV + 29)
 #define LIBERTAS_LED_GPIO_CTRL                 5
-#define LIBERTAS_BCN_CTRL               6
+#define LIBERTAS_BCN_CTRL                      6
+#define LIBERTAS_LED_BEHAVIOR_CTRL             7
 
 /** wlan_ioctl_regrdwr */
 struct wlan_ioctl_regrdwr {
-- 
1.5.2.4



_______________________________________________
Devel mailing list
[email protected]
http://lists.laptop.org/listinfo/devel

Reply via email to