[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