[PATCH] More control on LED behavior.

Javier Cardona javier at cozybit.com
Wed Oct 24 18:42:29 EDT 2007


From: Brajesh Dave <brajeshd at marvell.com>

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 <ashishs at marvell.com>
Signed-off-by: Javier Cardona <javier at cozybit.com>
---
 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






More information about the Devel mailing list