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
