| /******************************************************************************* |
| * Agere Systems Inc. |
| * Wireless device driver for Linux (wlags49). |
| * |
| * Copyright (c) 1998-2003 Agere Systems Inc. |
| * All rights reserved. |
| * http://www.agere.com |
| * |
| * Initially developed by TriplePoint, Inc. |
| * http://www.triplepoint.com |
| * |
| *------------------------------------------------------------------------------ |
| * |
| * This file defines handling routines for the private IOCTLs |
| * |
| *------------------------------------------------------------------------------ |
| * |
| * SOFTWARE LICENSE |
| * |
| * This software is provided subject to the following terms and conditions, |
| * which you should read carefully before using the software. Using this |
| * software indicates your acceptance of these terms and conditions. If you do |
| * not agree with these terms and conditions, do not use the software. |
| * |
| * Copyright © 2003 Agere Systems Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source or binary forms, with or without |
| * modifications, are permitted provided that the following conditions are met: |
| * |
| * . Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following Disclaimer as comments in the code as |
| * well as in the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * . Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following Disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * . Neither the name of Agere Systems Inc. nor the names of the contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * Disclaimer |
| * |
| * THIS SOFTWARE IS PROVIDED AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY |
| * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN |
| * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| * include files |
| ******************************************************************************/ |
| #include <wl_version.h> |
| |
| #include <linux/if_arp.h> |
| #include <linux/ioport.h> |
| #include <linux/slab.h> |
| #include <linux/delay.h> |
| #include <linux/uaccess.h> |
| |
| #include <debug.h> |
| #include <hcf.h> |
| #include <hcfdef.h> |
| |
| #include <wl_if.h> |
| #include <wl_internal.h> |
| #include <wl_enc.h> |
| #include <wl_main.h> |
| #include <wl_priv.h> |
| #include <wl_util.h> |
| #include <wl_netdev.h> |
| |
| int wvlan_uil_connect(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_disconnect(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_action(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_block(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_unblock(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_send_diag_msg(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp); |
| int wvlan_uil_get_info(struct uilreq *urq, struct wl_private *lp); |
| |
| int cfg_driver_info(struct uilreq *urq, struct wl_private *lp); |
| int cfg_driver_identity(struct uilreq *urq, struct wl_private *lp); |
| |
| |
| /* If USE_UIL is not defined, then none of the UIL Interface code below will |
| be included in the build */ |
| #ifdef USE_UIL |
| |
| /******************************************************************************* |
| * wvlan_uil() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * The handler function for the UIL interface. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil(struct uilreq *urq, struct wl_private *lp) |
| { |
| int ioctl_ret = 0; |
| |
| switch (urq->command) { |
| case UIL_FUN_CONNECT: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_CONNECT\n"); |
| ioctl_ret = wvlan_uil_connect(urq, lp); |
| break; |
| case UIL_FUN_DISCONNECT: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_DISCONNECT\n"); |
| ioctl_ret = wvlan_uil_disconnect(urq, lp); |
| break; |
| case UIL_FUN_ACTION: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_ACTION\n"); |
| ioctl_ret = wvlan_uil_action(urq, lp); |
| break; |
| case UIL_FUN_SEND_DIAG_MSG: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_SEND_DIAG_MSG\n"); |
| ioctl_ret = wvlan_uil_send_diag_msg(urq, lp); |
| break; |
| case UIL_FUN_GET_INFO: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_GET_INFO\n"); |
| ioctl_ret = wvlan_uil_get_info(urq, lp); |
| break; |
| case UIL_FUN_PUT_INFO: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_PUT_INFO\n"); |
| ioctl_ret = wvlan_uil_put_info(urq, lp); |
| break; |
| default: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- UNSUPPORTED UIL CODE: 0x%X", urq->command); |
| ioctl_ret = -EOPNOTSUPP; |
| break; |
| } |
| return ioctl_ret; |
| } /* wvlan_uil */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_connect() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Connect to the UIL in order to make a request. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_connect(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| |
| if (!(lp->flags & WVLAN2_UIL_CONNECTED)) { |
| lp->flags |= WVLAN2_UIL_CONNECTED; |
| urq->hcfCtx = &(lp->hcfCtx); |
| urq->result = UIL_SUCCESS; |
| } else { |
| DBG_WARNING(DbgInfo, "UIL_ERR_IN_USE\n"); |
| urq->result = UIL_ERR_IN_USE; |
| } |
| |
| return result; |
| } /* wvlan_uil_connect */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_disconnect() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Disconnect from the UIL after a request has been completed. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_disconnect(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| if (lp->flags & WVLAN2_UIL_CONNECTED) { |
| lp->flags &= ~WVLAN2_UIL_CONNECTED; |
| /* |
| if (lp->flags & WVLAN2_UIL_BUSY) { |
| lp->flags &= ~WVLAN2_UIL_BUSY; |
| netif_start_queue(lp->dev); |
| } |
| */ |
| } |
| |
| urq->hcfCtx = NULL; |
| urq->result = UIL_SUCCESS; |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_disconnect */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_action() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Handler for the UIL_ACT_xxx subcodes associated with UIL_FUN_ACTION |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_action(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| ltv_t *ltv; |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| /* Make sure there's an LTV in the request buffer */ |
| ltv = (ltv_t *)urq->data; |
| if (ltv != NULL) { |
| /* Switch on the Type field of the LTV contained in the request |
| buffer */ |
| switch (ltv->typ) { |
| case UIL_ACT_BLOCK: |
| DBG_TRACE(DbgInfo, "UIL_ACT_BLOCK\n"); |
| result = wvlan_uil_block(urq, lp); |
| break; |
| case UIL_ACT_UNBLOCK: |
| DBG_TRACE(DbgInfo, "UIL_ACT_UNBLOCK\n"); |
| result = wvlan_uil_unblock(urq, lp); |
| break; |
| case UIL_ACT_SCAN: |
| DBG_TRACE(DbgInfo, "UIL_ACT_SCAN\n"); |
| urq->result = hcf_action(&(lp->hcfCtx), MDD_ACT_SCAN); |
| break; |
| case UIL_ACT_APPLY: |
| DBG_TRACE(DbgInfo, "UIL_ACT_APPLY\n"); |
| urq->result = wl_apply(lp); |
| break; |
| case UIL_ACT_RESET: |
| DBG_TRACE(DbgInfo, "UIL_ACT_RESET\n"); |
| urq->result = wl_go(lp); |
| break; |
| default: |
| DBG_WARNING(DbgInfo, "Unknown action code: 0x%x\n", ltv->typ); |
| break; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "Bad LTV for this action\n"); |
| urq->result = UIL_ERR_LEN; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_action */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_block() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Sets a block in the driver to prevent access to the card by other |
| * processes. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| |
| int wvlan_uil_block(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| if (capable(CAP_NET_ADMIN)) { |
| lp->flags |= WVLAN2_UIL_BUSY; |
| netif_stop_queue(lp->dev); |
| WL_WDS_NETIF_STOP_QUEUE(lp); |
| urq->result = UIL_SUCCESS; |
| } else { |
| DBG_ERROR(DbgInfo, "EPERM\n"); |
| urq->result = UIL_FAILURE; |
| result = -EPERM; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_block */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_unblock() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Unblocks the driver to restore access to the card by other processes. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_unblock(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| if (capable(CAP_NET_ADMIN)) { |
| if (lp->flags & WVLAN2_UIL_BUSY) { |
| lp->flags &= ~WVLAN2_UIL_BUSY; |
| netif_wake_queue(lp->dev); |
| WL_WDS_NETIF_WAKE_QUEUE(lp); |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "EPERM\n"); |
| urq->result = UIL_FAILURE; |
| result = -EPERM; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_unblock */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_send_diag_msg() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Sends a diagnostic message to the card. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_send_diag_msg(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| DESC_STRCT Descp[1]; |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| if (capable(CAP_NET_ADMIN)) { |
| if ((urq->data != NULL) && (urq->len != 0)) { |
| if (lp->hcfCtx.IFB_RscInd != 0) { |
| u_char *data; |
| |
| /* Verify the user buffer */ |
| result = verify_area(VERIFY_READ, urq->data, urq->len); |
| if (result != 0) { |
| DBG_ERROR(DbgInfo, "verify_area failed, result: %d\n", result); |
| urq->result = UIL_FAILURE; |
| return result; |
| } |
| |
| data = kmalloc(urq->len, GFP_KERNEL); |
| if (data != NULL) { |
| memset(Descp, 0, sizeof(DESC_STRCT)); |
| memcpy(data, urq->data, urq->len); |
| |
| Descp[0].buf_addr = (wci_bufp)data; |
| Descp[0].BUF_CNT = urq->len; |
| Descp[0].next_desc_addr = 0; /* terminate list */ |
| |
| hcf_send_msg(&(lp->hcfCtx), &Descp[0], HCF_PORT_0); |
| kfree(data); |
| } else { |
| DBG_ERROR(DbgInfo, "ENOMEM\n"); |
| urq->result = UIL_FAILURE; |
| result = -ENOMEM; |
| return result; |
| } |
| |
| } else { |
| urq->result = UIL_ERR_BUSY; |
| } |
| |
| } else { |
| urq->result = UIL_FAILURE; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "EPERM\n"); |
| urq->result = UIL_FAILURE; |
| result = -EPERM; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_send_diag_msg */ |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wvlan_uil_put_info() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Sends a specific RID directly to the driver to set configuration info. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| ltv_t *pLtv; |
| bool_t ltvAllocated = FALSE; |
| ENCSTRCT sEncryption; |
| size_t len; |
| |
| #ifdef USE_WDS |
| hcf_16 hcfPort = HCF_PORT_0; |
| #endif /* USE_WDS */ |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| if (capable(CAP_NET_ADMIN)) { |
| if ((urq->data != NULL) && (urq->len != 0)) { |
| /* Make sure that we have at least a command and length to send. */ |
| if (urq->len < (sizeof(hcf_16) * 2)) { |
| urq->len = sizeof(lp->ltvRecord); |
| urq->result = UIL_ERR_LEN; |
| DBG_ERROR(DbgInfo, "No Length/Type in LTV!!!\n"); |
| DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n"); |
| return result; |
| } |
| |
| /* Verify the user buffer */ |
| result = verify_area(VERIFY_READ, urq->data, urq->len); |
| if (result != 0) { |
| urq->result = UIL_FAILURE; |
| DBG_ERROR(DbgInfo, "verify_area(), VERIFY_READ FAILED\n"); |
| return result; |
| } |
| |
| /* Get only the command and length information. */ |
| copy_from_user(&(lp->ltvRecord), urq->data, sizeof(hcf_16) * 2); |
| |
| /* Make sure the incoming LTV record length is within the bounds of the |
| IOCTL length */ |
| if (((lp->ltvRecord.len + 1) * sizeof(hcf_16)) > urq->len) { |
| urq->len = sizeof(lp->ltvRecord); |
| urq->result = UIL_ERR_LEN; |
| DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n"); |
| return result; |
| } |
| |
| /* If the requested length is greater than the size of our local |
| LTV record, try to allocate it from the kernel stack. |
| Otherwise, we just use our local LTV record. */ |
| if (urq->len > sizeof(lp->ltvRecord)) { |
| pLtv = kmalloc(urq->len, GFP_KERNEL); |
| if (pLtv != NULL) { |
| ltvAllocated = TRUE; |
| } else { |
| DBG_ERROR(DbgInfo, "Alloc FAILED\n"); |
| urq->len = sizeof(lp->ltvRecord); |
| urq->result = UIL_ERR_LEN; |
| result = -ENOMEM; |
| return result; |
| } |
| } else { |
| pLtv = &(lp->ltvRecord); |
| } |
| |
| /* Copy the data from the user's buffer into the local LTV |
| record data area. */ |
| copy_from_user(pLtv, urq->data, urq->len); |
| |
| |
| /* We need to snoop the commands to see if there is anything we |
| need to store for the purposes of a reset or start/stop |
| sequence. Perform endian translation as needed */ |
| switch (pLtv->typ) { |
| case CFG_CNF_PORT_TYPE: |
| lp->PortType = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_OWN_MAC_ADDR: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| case CFG_CNF_OWN_CHANNEL: |
| lp->Channel = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| /* CFG_CNF_OWN_SSID currently same as CNF_DESIRED_SSID. Do we |
| need separate storage for this? */ |
| /* case CFG_CNF_OWN_SSID: */ |
| case CFG_CNF_OWN_ATIM_WINDOW: |
| lp->atimWindow = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_SYSTEM_SCALE: |
| lp->DistanceBetweenAPs = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| |
| case CFG_CNF_MAX_DATA_LEN: |
| /* TODO: determine if we are going to store anything based |
| on this */ |
| break; |
| case CFG_CNF_PM_ENABLED: |
| lp->PMEnabled = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_MCAST_RX: |
| lp->MulticastReceive = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_MAX_SLEEP_DURATION: |
| lp->MaxSleepDuration = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_HOLDOVER_DURATION: |
| lp->holdoverDuration = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_OWN_NAME: |
| memset(lp->StationName, 0, sizeof(lp->StationName)); |
| len = min_t(size_t, pLtv->u.u16[0], sizeof(lp->StationName)); |
| strlcpy(lp->StationName, &pLtv->u.u8[2], len); |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_LOAD_BALANCING: |
| lp->loadBalancing = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_MEDIUM_DISTRIBUTION: |
| lp->mediumDistribution = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #ifdef WARP |
| case CFG_CNF_TX_POW_LVL: |
| lp->txPowLevel = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| /* case CFG_CNF_SHORT_RETRY_LIMIT: */ /* Short Retry Limit */ |
| /* case 0xFC33: */ /* Long Retry Limit */ |
| case CFG_SUPPORTED_RATE_SET_CNTL: /* Supported Rate Set Control */ |
| lp->srsc[0] = pLtv->u.u16[0]; |
| lp->srsc[1] = pLtv->u.u16[1]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| pLtv->u.u16[1] = CNV_INT_TO_LITTLE(pLtv->u.u16[1]); |
| break; |
| case CFG_BASIC_RATE_SET_CNTL: /* Basic Rate Set Control */ |
| lp->brsc[0] = pLtv->u.u16[0]; |
| lp->brsc[1] = pLtv->u.u16[1]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| pLtv->u.u16[1] = CNV_INT_TO_LITTLE(pLtv->u.u16[1]); |
| break; |
| case CFG_CNF_CONNECTION_CNTL: |
| lp->connectionControl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| /* case CFG_PROBE_DATA_RATE: */ |
| #endif /* HERMES25 */ |
| |
| #if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */ |
| /* ;?should we restore this to allow smaller memory footprint */ |
| |
| case CFG_CNF_OWN_DTIM_PERIOD: |
| lp->DTIMPeriod = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #ifdef WARP |
| case CFG_CNF_OWN_BEACON_INTERVAL: /* Own Beacon Interval */ |
| lp->ownBeaconInterval = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #endif /* WARP */ |
| case CFG_COEXISTENSE_BEHAVIOUR: /* Coexistence behavior */ |
| lp->coexistence = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #ifdef USE_WDS |
| case CFG_CNF_WDS_ADDR1: |
| memcpy(&lp->wds_port[0].wdsAddress, &pLtv->u.u8[0], ETH_ALEN); |
| hcfPort = HCF_PORT_1; |
| break; |
| case CFG_CNF_WDS_ADDR2: |
| memcpy(&lp->wds_port[1].wdsAddress, &pLtv->u.u8[0], ETH_ALEN); |
| hcfPort = HCF_PORT_2; |
| break; |
| case CFG_CNF_WDS_ADDR3: |
| memcpy(&lp->wds_port[2].wdsAddress, &pLtv->u.u8[0], ETH_ALEN); |
| hcfPort = HCF_PORT_3; |
| break; |
| case CFG_CNF_WDS_ADDR4: |
| memcpy(&lp->wds_port[3].wdsAddress, &pLtv->u.u8[0], ETH_ALEN); |
| hcfPort = HCF_PORT_4; |
| break; |
| case CFG_CNF_WDS_ADDR5: |
| memcpy(&lp->wds_port[4].wdsAddress, &pLtv->u.u8[0], ETH_ALEN); |
| hcfPort = HCF_PORT_5; |
| break; |
| case CFG_CNF_WDS_ADDR6: |
| memcpy(&lp->wds_port[5].wdsAddress, &pLtv->u.u8[0], ETH_ALEN); |
| hcfPort = HCF_PORT_6; |
| break; |
| #endif /* USE_WDS */ |
| |
| case CFG_CNF_MCAST_PM_BUF: |
| lp->multicastPMBuffering = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_REJECT_ANY: |
| lp->RejectAny = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #endif |
| |
| case CFG_CNF_ENCRYPTION: |
| lp->EnableEncryption = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_CNF_AUTHENTICATION: |
| lp->authentication = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */ |
| /* ;?should we restore this to allow smaller memory footprint */ |
| |
| /* case CFG_CNF_EXCL_UNENCRYPTED: |
| lp->ExcludeUnencrypted = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; */ |
| case CFG_CNF_MCAST_RATE: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| case CFG_CNF_INTRA_BSS_RELAY: |
| lp->intraBSSRelay = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #endif |
| |
| case CFG_CNF_MICRO_WAVE: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| /*case CFG_CNF_LOAD_BALANCING:*/ |
| /* TODO: determine if we are going to store anything based on this */ |
| /* break; */ |
| /* case CFG_CNF_MEDIUM_DISTRIBUTION: */ |
| /* TODO: determine if we are going to store anything based on this */ |
| /* break; */ |
| /* case CFG_CNF_RX_ALL_GROUP_ADDRESS: */ |
| /* TODO: determine if we are going to store anything based on this */ |
| /* break; */ |
| /* case CFG_CNF_COUNTRY_INFO: */ |
| /* TODO: determine if we are going to store anything based on this */ |
| /* break; */ |
| case CFG_CNF_OWN_SSID: |
| /* case CNF_DESIRED_SSID: */ |
| case CFG_DESIRED_SSID: |
| memset(lp->NetworkName, 0, sizeof(lp->NetworkName)); |
| memcpy((void *)lp->NetworkName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]); |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| |
| /* take care of the special network name "ANY" case */ |
| if ((strlen(&pLtv->u.u8[2]) == 0) || |
| (strcmp(&pLtv->u.u8[2], "ANY") == 0) || |
| (strcmp(&pLtv->u.u8[2], "any") == 0)) { |
| /* set the SSID_STRCT llen field (u16[0]) to zero, and the |
| effectually null the string u8[2] */ |
| pLtv->u.u16[0] = 0; |
| pLtv->u.u8[2] = 0; |
| } |
| break; |
| case CFG_GROUP_ADDR: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| case CFG_CREATE_IBSS: |
| lp->CreateIBSS = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_RTS_THRH: |
| lp->RTSThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_TX_RATE_CNTL: |
| lp->TxRateControl[0] = pLtv->u.u16[0]; |
| lp->TxRateControl[1] = pLtv->u.u16[1]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| pLtv->u.u16[1] = CNV_INT_TO_LITTLE(pLtv->u.u16[1]); |
| break; |
| case CFG_PROMISCUOUS_MODE: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| /* case CFG_WAKE_ON_LAN: */ |
| /* TODO: determine if we are going to store anything based on this */ |
| /* break; */ |
| #if 1 /* ;? #if (HCF_TYPE) & HCF_TYPE_AP */ |
| /* ;?should we restore this to allow smaller memory footprint */ |
| case CFG_RTS_THRH0: |
| lp->RTSThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_TX_RATE_CNTL0: |
| /*;?no idea what this should be, get going so comment it out lp->TxRateControl = pLtv->u.u16[0];*/ |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| #ifdef USE_WDS |
| case CFG_RTS_THRH1: |
| lp->wds_port[0].rtsThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_1; |
| break; |
| case CFG_RTS_THRH2: |
| lp->wds_port[1].rtsThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_2; |
| break; |
| case CFG_RTS_THRH3: |
| lp->wds_port[2].rtsThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_3; |
| break; |
| case CFG_RTS_THRH4: |
| lp->wds_port[3].rtsThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_4; |
| break; |
| case CFG_RTS_THRH5: |
| lp->wds_port[4].rtsThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_5; |
| break; |
| case CFG_RTS_THRH6: |
| lp->wds_port[5].rtsThreshold = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_6; |
| break; |
| case CFG_TX_RATE_CNTL1: |
| lp->wds_port[0].txRateCntl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_1; |
| break; |
| case CFG_TX_RATE_CNTL2: |
| lp->wds_port[1].txRateCntl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_2; |
| break; |
| case CFG_TX_RATE_CNTL3: |
| lp->wds_port[2].txRateCntl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_3; |
| break; |
| case CFG_TX_RATE_CNTL4: |
| lp->wds_port[3].txRateCntl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_4; |
| break; |
| case CFG_TX_RATE_CNTL5: |
| lp->wds_port[4].txRateCntl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_5; |
| break; |
| case CFG_TX_RATE_CNTL6: |
| lp->wds_port[5].txRateCntl = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| hcfPort = HCF_PORT_6; |
| break; |
| #endif /* USE_WDS */ |
| #endif /* (HCF_TYPE) & HCF_TYPE_AP */ |
| |
| case CFG_DEFAULT_KEYS: |
| { |
| CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)pLtv; |
| |
| pKeys->key[0].len = CNV_INT_TO_LITTLE(pKeys->key[0].len); |
| pKeys->key[1].len = CNV_INT_TO_LITTLE(pKeys->key[1].len); |
| pKeys->key[2].len = CNV_INT_TO_LITTLE(pKeys->key[2].len); |
| pKeys->key[3].len = CNV_INT_TO_LITTLE(pKeys->key[3].len); |
| |
| memcpy((void *)&(lp->DefaultKeys), (void *)pKeys, |
| sizeof(CFG_DEFAULT_KEYS_STRCT)); |
| } |
| break; |
| case CFG_TX_KEY_ID: |
| lp->TransmitKeyID = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_SCAN_SSID: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| case CFG_TICK_TIME: |
| /* TODO: determine if we are going to store anything based on this */ |
| break; |
| /* these RIDS are Info RIDs, and should they be allowed for puts??? */ |
| case CFG_MAX_LOAD_TIME: |
| case CFG_DL_BUF: |
| /* case CFG_HSI_SUP_RANGE: */ |
| case CFG_NIC_SERIAL_NUMBER: |
| case CFG_NIC_IDENTITY: |
| case CFG_NIC_MFI_SUP_RANGE: |
| case CFG_NIC_CFI_SUP_RANGE: |
| case CFG_NIC_TEMP_TYPE: |
| case CFG_NIC_PROFILE: |
| case CFG_FW_IDENTITY: |
| case CFG_FW_SUP_RANGE: |
| case CFG_MFI_ACT_RANGES_STA: |
| case CFG_CFI_ACT_RANGES_STA: |
| case CFG_PORT_STAT: |
| case CFG_CUR_SSID: |
| case CFG_CUR_BSSID: |
| case CFG_COMMS_QUALITY: |
| case CFG_CUR_TX_RATE: |
| case CFG_CUR_BEACON_INTERVAL: |
| case CFG_CUR_SCALE_THRH: |
| case CFG_PROTOCOL_RSP_TIME: |
| case CFG_CUR_SHORT_RETRY_LIMIT: |
| case CFG_CUR_LONG_RETRY_LIMIT: |
| case CFG_MAX_TX_LIFETIME: |
| case CFG_MAX_RX_LIFETIME: |
| case CFG_CF_POLLABLE: |
| case CFG_AUTHENTICATION_ALGORITHMS: |
| case CFG_PRIVACY_OPT_IMPLEMENTED: |
| /* case CFG_CURRENT_REMOTE_RATES: */ |
| /* case CFG_CURRENT_USED_RATES: */ |
| /* case CFG_CURRENT_SYSTEM_SCALE: */ |
| /* case CFG_CURRENT_TX_RATE1: */ |
| /* case CFG_CURRENT_TX_RATE2: */ |
| /* case CFG_CURRENT_TX_RATE3: */ |
| /* case CFG_CURRENT_TX_RATE4: */ |
| /* case CFG_CURRENT_TX_RATE5: */ |
| /* case CFG_CURRENT_TX_RATE6: */ |
| case CFG_NIC_MAC_ADDR: |
| case CFG_PCF_INFO: |
| /* case CFG_CURRENT_COUNTRY_INFO: */ |
| case CFG_PHY_TYPE: |
| case CFG_CUR_CHANNEL: |
| /* case CFG_CURRENT_POWER_STATE: */ |
| /* case CFG_CCAMODE: */ |
| case CFG_SUPPORTED_DATA_RATES: |
| break; |
| case CFG_AP_MODE: |
| /*;? lp->DownloadFirmware = (pLtv->u.u16[0]) + 1; */ |
| DBG_ERROR(DbgInfo, "set CFG_AP_MODE no longer supported\n"); |
| break; |
| case CFG_ENCRYPT_STRING: |
| /* TODO: ENDIAN TRANSLATION HERE??? */ |
| memset(lp->szEncryption, 0, sizeof(lp->szEncryption)); |
| memcpy((void *)lp->szEncryption, (void *)&pLtv->u.u8[0], |
| (pLtv->len * sizeof(hcf_16))); |
| wl_wep_decode(CRYPT_CODE, &sEncryption, |
| lp->szEncryption); |
| |
| /* the Linux driver likes to use 1-4 for the key IDs, and then |
| convert to 0-3 when sending to the card. The Windows code |
| base used 0-3 in the API DLL, which was ported to Linux. For |
| the sake of the user experience, we decided to keep 0-3 as the |
| numbers used in the DLL; and will perform the +1 conversion here. |
| We could have converted the entire Linux driver, but this is |
| less obtrusive. This may be a "todo" to convert the whole driver */ |
| lp->TransmitKeyID = sEncryption.wTxKeyID + 1; |
| lp->EnableEncryption = sEncryption.wEnabled; |
| |
| memcpy(&lp->DefaultKeys, &sEncryption.EncStr, |
| sizeof(CFG_DEFAULT_KEYS_STRCT)); |
| break; |
| /*case CFG_COUNTRY_STRING: |
| memset(lp->countryString, 0, sizeof(lp->countryString)); |
| memcpy((void *)lp->countryString, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]); |
| break; |
| */ |
| |
| case CFG_DRIVER_ENABLE: |
| lp->driverEnable = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_WOLAS_ENABLE: |
| lp->wolasEnable = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_SET_WPA_AUTH_KEY_MGMT_SUITE: |
| lp->AuthKeyMgmtSuite = pLtv->u.u16[0]; |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_DISASSOCIATE_ADDR: |
| pLtv->u.u16[ETH_ALEN / 2] = CNV_INT_TO_LITTLE(pLtv->u.u16[ETH_ALEN / 2]); |
| break; |
| case CFG_ADD_TKIP_DEFAULT_KEY: |
| case CFG_REMOVE_TKIP_DEFAULT_KEY: |
| /* Endian convert the Tx Key Information */ |
| pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); |
| break; |
| case CFG_ADD_TKIP_MAPPED_KEY: |
| break; |
| case CFG_REMOVE_TKIP_MAPPED_KEY: |
| break; |
| /* some RIDs just can't be put */ |
| case CFG_MB_INFO: |
| case CFG_IFB: |
| default: |
| break; |
| } |
| |
| /* This code will prevent Static Configuration Entities from |
| being sent to the card, as they require a call to |
| UIL_ACT_APPLY to take effect. Dynamic Entities will be sent |
| immediately */ |
| switch (pLtv->typ) { |
| case CFG_CNF_PORT_TYPE: |
| case CFG_CNF_OWN_MAC_ADDR: |
| case CFG_CNF_OWN_CHANNEL: |
| case CFG_CNF_OWN_SSID: |
| case CFG_CNF_OWN_ATIM_WINDOW: |
| case CFG_CNF_SYSTEM_SCALE: |
| case CFG_CNF_MAX_DATA_LEN: |
| case CFG_CNF_PM_ENABLED: |
| case CFG_CNF_MCAST_RX: |
| case CFG_CNF_MAX_SLEEP_DURATION: |
| case CFG_CNF_HOLDOVER_DURATION: |
| case CFG_CNF_OWN_NAME: |
| case CFG_CNF_LOAD_BALANCING: |
| case CFG_CNF_MEDIUM_DISTRIBUTION: |
| #ifdef WARP |
| case CFG_CNF_TX_POW_LVL: |
| case CFG_CNF_CONNECTION_CNTL: |
| /*case CFG_PROBE_DATA_RATE: */ |
| #endif /* HERMES25 */ |
| #if 1 /*;? (HCF_TYPE) & HCF_TYPE_AP */ |
| /*;?should we restore this to allow smaller memory footprint */ |
| case CFG_CNF_OWN_DTIM_PERIOD: |
| #ifdef WARP |
| case CFG_CNF_OWN_BEACON_INTERVAL: /* Own Beacon Interval */ |
| #endif /* WARP */ |
| #ifdef USE_WDS |
| case CFG_CNF_WDS_ADDR1: |
| case CFG_CNF_WDS_ADDR2: |
| case CFG_CNF_WDS_ADDR3: |
| case CFG_CNF_WDS_ADDR4: |
| case CFG_CNF_WDS_ADDR5: |
| case CFG_CNF_WDS_ADDR6: |
| #endif |
| case CFG_CNF_MCAST_PM_BUF: |
| case CFG_CNF_REJECT_ANY: |
| #endif |
| |
| case CFG_CNF_ENCRYPTION: |
| case CFG_CNF_AUTHENTICATION: |
| #if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */ |
| /* ;?should we restore this to allow smaller memory footprint */ |
| |
| case CFG_CNF_EXCL_UNENCRYPTED: |
| case CFG_CNF_MCAST_RATE: |
| case CFG_CNF_INTRA_BSS_RELAY: |
| #endif |
| |
| case CFG_CNF_MICRO_WAVE: |
| /* case CFG_CNF_LOAD_BALANCING: */ |
| /* case CFG_CNF_MEDIUM_DISTRIBUTION: */ |
| /* case CFG_CNF_RX_ALL_GROUP_ADDRESS: */ |
| /* case CFG_CNF_COUNTRY_INFO: */ |
| /* case CFG_COUNTRY_STRING: */ |
| case CFG_AP_MODE: |
| case CFG_ENCRYPT_STRING: |
| /* case CFG_DRIVER_ENABLE: */ |
| case CFG_WOLAS_ENABLE: |
| case CFG_MB_INFO: |
| case CFG_IFB: |
| break; |
| /* Deal with this dynamic MSF RID, as it's required for WPA */ |
| case CFG_DRIVER_ENABLE: |
| if (lp->driverEnable) { |
| hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0); |
| hcf_cntl(&(lp->hcfCtx), HCF_CNTL_CONNECT); |
| } else { |
| hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0); |
| hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISCONNECT); |
| } |
| break; |
| default: |
| wl_act_int_off(lp); |
| urq->result = hcf_put_info(&(lp->hcfCtx), (LTVP) pLtv); |
| wl_act_int_on(lp); |
| break; |
| } |
| |
| if (ltvAllocated) |
| kfree(pLtv); |
| } else { |
| urq->result = UIL_FAILURE; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "EPERM\n"); |
| urq->result = UIL_FAILURE; |
| result = -EPERM; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_put_info */ |
| |
| /*============================================================================*/ |
| |
| /******************************************************************************* |
| * wvlan_uil_get_info() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Sends a specific RID directly to the driver to retrieve configuration |
| * info. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_uil_get_info(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| int i; |
| |
| if (urq->hcfCtx == &(lp->hcfCtx)) { |
| if ((urq->data != NULL) && (urq->len != 0)) { |
| ltv_t *pLtv; |
| bool_t ltvAllocated = FALSE; |
| |
| /* Make sure that we have at least a command and length */ |
| if (urq->len < (sizeof(hcf_16) * 2)) { |
| urq->len = sizeof(lp->ltvRecord); |
| DBG_ERROR(DbgInfo, "No Length/Type in LTV!!!\n"); |
| DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n"); |
| urq->result = UIL_ERR_LEN; |
| return result; |
| } |
| |
| /* Verify the user's LTV record header. */ |
| result = verify_area(VERIFY_READ, urq->data, sizeof(hcf_16) * 2); |
| if (result != 0) { |
| DBG_ERROR(DbgInfo, "verify_area(), VERIFY_READ FAILED\n"); |
| urq->result = UIL_FAILURE; |
| return result; |
| } |
| |
| /* Get only the command and length information. */ |
| result = copy_from_user(&(lp->ltvRecord), urq->data, sizeof(hcf_16) * 2); |
| |
| /* Make sure the incoming LTV record length is within the bounds of |
| the IOCTL length. */ |
| if (((lp->ltvRecord.len + 1) * sizeof(hcf_16)) > urq->len) { |
| DBG_ERROR(DbgInfo, "Incoming LTV too big\n"); |
| urq->len = sizeof(lp->ltvRecord); |
| urq->result = UIL_ERR_LEN; |
| return result; |
| } |
| |
| /* Determine if hcf_get_info() is needed or not */ |
| switch (lp->ltvRecord.typ) { |
| case CFG_NIC_IDENTITY: |
| memcpy(&lp->ltvRecord.u.u8[0], &lp->NICIdentity, sizeof(lp->NICIdentity)); |
| break; |
| case CFG_PRI_IDENTITY: |
| memcpy(&lp->ltvRecord.u.u8[0], &lp->PrimaryIdentity, sizeof(lp->PrimaryIdentity)); |
| break; |
| case CFG_AP_MODE: |
| DBG_ERROR(DbgInfo, "set CFG_AP_MODE no longer supported, so is get useful ????\n"); |
| lp->ltvRecord.u.u16[0] = |
| CNV_INT_TO_LITTLE(lp->hcfCtx.IFB_FWIdentity.comp_id) == COMP_ID_FW_AP; |
| break; |
| /* case CFG_DRV_INFO: */ |
| case CFG_ENCRYPT_STRING: |
| case CFG_COUNTRY_STRING: |
| case CFG_DRIVER_ENABLE: |
| case CFG_WOLAS_ENABLE: |
| /* TODO: determine if we're going to support these */ |
| urq->result = UIL_FAILURE; |
| break; |
| case CFG_DRV_INFO: |
| DBG_TRACE(DbgInfo, "Intercept CFG_DRV_INFO\n"); |
| result = cfg_driver_info(urq, lp); |
| break; |
| case CFG_DRV_IDENTITY: |
| DBG_TRACE(DbgInfo, "Intercept CFG_DRV_IDENTITY\n"); |
| result = cfg_driver_identity(urq, lp); |
| break; |
| case CFG_IFB: |
| /* IFB can be a security hole */ |
| if (!capable(CAP_NET_ADMIN)) { |
| result = -EPERM; |
| break; |
| } |
| |
| /* Else fall through to the default */ |
| |
| case CFG_FW_IDENTITY: /* For Hermes-1, this is cached */ |
| default: |
| |
| /* Verify the user buffer */ |
| result = verify_area(VERIFY_WRITE, urq->data, urq->len); |
| if (result != 0) { |
| DBG_ERROR(DbgInfo, "verify_area(), VERIFY_WRITE FAILED\n"); |
| urq->result = UIL_FAILURE; |
| break; |
| } |
| |
| /* If the requested length is greater than the size of our local |
| LTV record, try to allocate it from the kernel stack. |
| Otherwise, we just use our local LTV record. */ |
| if (urq->len > sizeof(lp->ltvRecord)) { |
| pLtv = kmalloc(urq->len, GFP_KERNEL); |
| if (pLtv != NULL) { |
| ltvAllocated = TRUE; |
| |
| /* Copy the command/length information into the new buffer. */ |
| memcpy(pLtv, &(lp->ltvRecord), sizeof(hcf_16) * 2); |
| } else { |
| urq->len = sizeof(lp->ltvRecord); |
| urq->result = UIL_ERR_LEN; |
| DBG_ERROR(DbgInfo, "kmalloc FAILED\n"); |
| DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n"); |
| result = -ENOMEM; |
| break; |
| } |
| } else { |
| pLtv = &(lp->ltvRecord); |
| } |
| |
| wl_act_int_off(lp); |
| urq->result = hcf_get_info(&(lp->hcfCtx), (LTVP) pLtv); |
| wl_act_int_on(lp); |
| |
| /* Copy the LTV into the user's buffer. */ |
| /*copy_to_user(urq->data, pLtv, urq->len); */ |
| |
| /*if(ltvAllocated) |
| { |
| kfree(pLtv); |
| }*/ |
| |
| /* urq->result = UIL_SUCCESS; */ |
| break; |
| } |
| |
| /* Handle endian conversion of special fields */ |
| switch (lp->ltvRecord.typ) { |
| /* simple int gets just need the first hcf_16 byte flipped */ |
| case CFG_CNF_PORT_TYPE: |
| case CFG_CNF_OWN_CHANNEL: |
| case CFG_CNF_OWN_ATIM_WINDOW: |
| case CFG_CNF_SYSTEM_SCALE: |
| case CFG_CNF_MAX_DATA_LEN: |
| case CFG_CNF_PM_ENABLED: |
| case CFG_CNF_MCAST_RX: |
| case CFG_CNF_MAX_SLEEP_DURATION: |
| case CFG_CNF_HOLDOVER_DURATION: |
| case CFG_CNF_OWN_DTIM_PERIOD: |
| case CFG_CNF_MCAST_PM_BUF: |
| case CFG_CNF_REJECT_ANY: |
| case CFG_CNF_ENCRYPTION: |
| case CFG_CNF_AUTHENTICATION: |
| case CFG_CNF_EXCL_UNENCRYPTED: |
| case CFG_CNF_INTRA_BSS_RELAY: |
| case CFG_CNF_MICRO_WAVE: |
| case CFG_CNF_LOAD_BALANCING: |
| case CFG_CNF_MEDIUM_DISTRIBUTION: |
| #ifdef WARP |
| case CFG_CNF_TX_POW_LVL: |
| case CFG_CNF_CONNECTION_CNTL: |
| case CFG_CNF_OWN_BEACON_INTERVAL: /* Own Beacon Interval */ |
| case CFG_COEXISTENSE_BEHAVIOUR: /* Coexistence Behavior */ |
| /*case CFG_CNF_RX_ALL_GROUP_ADDRESS: */ |
| #endif /* HERMES25 */ |
| case CFG_CREATE_IBSS: |
| case CFG_RTS_THRH: |
| case CFG_PROMISCUOUS_MODE: |
| /*case CFG_WAKE_ON_LAN: */ |
| case CFG_RTS_THRH0: |
| case CFG_RTS_THRH1: |
| case CFG_RTS_THRH2: |
| case CFG_RTS_THRH3: |
| case CFG_RTS_THRH4: |
| case CFG_RTS_THRH5: |
| case CFG_RTS_THRH6: |
| case CFG_TX_RATE_CNTL0: |
| case CFG_TX_RATE_CNTL1: |
| case CFG_TX_RATE_CNTL2: |
| case CFG_TX_RATE_CNTL3: |
| case CFG_TX_RATE_CNTL4: |
| case CFG_TX_RATE_CNTL5: |
| case CFG_TX_RATE_CNTL6: |
| case CFG_TX_KEY_ID: |
| case CFG_TICK_TIME: |
| case CFG_MAX_LOAD_TIME: |
| case CFG_NIC_TEMP_TYPE: |
| case CFG_PORT_STAT: |
| case CFG_CUR_TX_RATE: |
| case CFG_CUR_BEACON_INTERVAL: |
| case CFG_PROTOCOL_RSP_TIME: |
| case CFG_CUR_SHORT_RETRY_LIMIT: |
| case CFG_CUR_LONG_RETRY_LIMIT: |
| case CFG_MAX_TX_LIFETIME: |
| case CFG_MAX_RX_LIFETIME: |
| case CFG_CF_POLLABLE: |
| case CFG_PRIVACY_OPT_IMPLEMENTED: |
| /* case CFG_CURRENT_REMOTE_RATES: */ |
| /* case CFG_CURRENT_USED_RATES: */ |
| /* case CFG_CURRENT_SYSTEM_SCALE: */ |
| /* case CFG_CURRENT_TX_RATE1: */ |
| /* case CFG_CURRENT_TX_RATE2: */ |
| /* case CFG_CURRENT_TX_RATE3: */ |
| /* case CFG_CURRENT_TX_RATE4: */ |
| /* case CFG_CURRENT_TX_RATE5: */ |
| /* case CFG_CURRENT_TX_RATE6: */ |
| case CFG_PHY_TYPE: |
| case CFG_CUR_CHANNEL: |
| /* case CFG_CURRENT_POWER_STATE: */ |
| /* case CFG_CCAMODE: */ |
| /* lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); */ |
| /* break; */ |
| /* name string gets just need the first hcf_16 byte flipped (length of string) */ |
| case CFG_CNF_OWN_SSID: |
| case CFG_CNF_OWN_NAME: |
| /* case CNF_DESIRED_SSID: */ |
| case CFG_DESIRED_SSID: |
| case CFG_SCAN_SSID: |
| case CFG_CUR_SSID: |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); |
| break; |
| /* non-length counted strings need no byte flipping */ |
| case CFG_CNF_OWN_MAC_ADDR: |
| /* this case is no longer valid: CFG_CNF_WDS_ADDR */ |
| case CFG_CNF_WDS_ADDR1: |
| case CFG_CNF_WDS_ADDR2: |
| case CFG_CNF_WDS_ADDR3: |
| case CFG_CNF_WDS_ADDR4: |
| case CFG_CNF_WDS_ADDR5: |
| case CFG_CNF_WDS_ADDR6: |
| case CFG_GROUP_ADDR: |
| case CFG_NIC_SERIAL_NUMBER: |
| case CFG_CUR_BSSID: |
| case CFG_NIC_MAC_ADDR: |
| case CFG_SUPPORTED_DATA_RATES: /* need to ensure we can treat this as a string */ |
| break; |
| /* case CFG_CNF_COUNTRY_INFO: */ /* special case, see page 75 of 022486, Rev C. */ |
| /* case CFG_CURRENT_COUNTRY_INFO: */ /* special case, see page 101 of 022486, Rev C. */ |
| /* |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); |
| lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[3]); |
| |
| for(i = 4; i < lp->ltvRecord.len; i++) { |
| lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[i]); |
| } |
| break; |
| */ |
| |
| case CFG_DEFAULT_KEYS: |
| { |
| CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)&lp->ltvRecord.u.u8[0]; |
| |
| pKeys[0].len = CNV_INT_TO_LITTLE(pKeys[0].len); |
| pKeys[1].len = CNV_INT_TO_LITTLE(pKeys[1].len); |
| pKeys[2].len = CNV_INT_TO_LITTLE(pKeys[2].len); |
| pKeys[3].len = CNV_INT_TO_LITTLE(pKeys[3].len); |
| } |
| break; |
| case CFG_CNF_MCAST_RATE: |
| case CFG_TX_RATE_CNTL: |
| case CFG_SUPPORTED_RATE_SET_CNTL: /* Supported Rate Set Control */ |
| case CFG_BASIC_RATE_SET_CNTL: /* Basic Rate Set Control */ |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]); |
| break; |
| case CFG_DL_BUF: |
| case CFG_NIC_IDENTITY: |
| case CFG_COMMS_QUALITY: |
| case CFG_PCF_INFO: |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]); |
| lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[2]); |
| break; |
| case CFG_FW_IDENTITY: |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]); |
| lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[2]); |
| lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[3]); |
| break; |
| /* case CFG_HSI_SUP_RANGE: */ |
| case CFG_NIC_MFI_SUP_RANGE: |
| case CFG_NIC_CFI_SUP_RANGE: |
| case CFG_NIC_PROFILE: |
| case CFG_FW_SUP_RANGE: |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]); |
| lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[2]); |
| lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[3]); |
| lp->ltvRecord.u.u16[4] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[4]); |
| break; |
| case CFG_MFI_ACT_RANGES_STA: |
| case CFG_CFI_ACT_RANGES_STA: |
| case CFG_CUR_SCALE_THRH: |
| case CFG_AUTHENTICATION_ALGORITHMS: |
| for (i = 0; i < (lp->ltvRecord.len - 1); i++) |
| lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[i]); |
| break; |
| /* done at init time, and endian handled then */ |
| case CFG_PRI_IDENTITY: |
| break; |
| case CFG_MB_INFO: |
| /* wvlanEndianTranslateMailbox(pLtv); */ |
| break; |
| /* MSF and HCF RIDS */ |
| case CFG_IFB: |
| case CFG_DRV_INFO: |
| case CFG_AP_MODE: |
| case CFG_ENCRYPT_STRING: |
| case CFG_COUNTRY_STRING: |
| case CFG_DRIVER_ENABLE: |
| case CFG_WOLAS_ENABLE: |
| default: |
| break; |
| } |
| |
| /* Copy the LTV into the user's buffer. */ |
| copy_to_user(urq->data, &(lp->ltvRecord), urq->len); |
| |
| if (ltvAllocated) |
| kfree(&(lp->ltvRecord)); |
| urq->result = UIL_SUCCESS; |
| } else { |
| urq->result = UIL_FAILURE; |
| } |
| } else { |
| DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n"); |
| urq->result = UIL_ERR_WRONG_IFB; |
| } |
| |
| return result; |
| } /* wvlan_uil_get_info */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| |
| /******************************************************************************* |
| * cfg_driver_info() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Retrieves driver information. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int cfg_driver_info(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| |
| /* Make sure that user buffer can handle the driver information buffer */ |
| if (urq->len < sizeof(lp->driverInfo)) { |
| urq->len = sizeof(lp->driverInfo); |
| urq->result = UIL_ERR_LEN; |
| return result; |
| } |
| |
| /* Verify the user buffer. */ |
| result = verify_area(VERIFY_WRITE, urq->data, sizeof(lp->driverInfo)); |
| if (result != 0) { |
| urq->result = UIL_FAILURE; |
| return result; |
| } |
| |
| lp->driverInfo.card_stat = lp->hcfCtx.IFB_CardStat; |
| |
| /* Copy the driver information into the user's buffer. */ |
| urq->result = UIL_SUCCESS; |
| copy_to_user(urq->data, &(lp->driverInfo), sizeof(lp->driverInfo)); |
| |
| return result; |
| } /* cfg_driver_info */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * cfg_driver_identity() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Retrieves ID information from the card. |
| * |
| * PARAMETERS: |
| * |
| * urq - a pointer to the UIL request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * UIL_SUCCESS |
| * UIL_ERR_xxx value otherwise |
| * |
| ******************************************************************************/ |
| int cfg_driver_identity(struct uilreq *urq, struct wl_private *lp) |
| { |
| int result = 0; |
| |
| /* Make sure that user buffer can handle the driver identity structure. */ |
| if (urq->len < sizeof(lp->driverIdentity)) { |
| urq->len = sizeof(lp->driverIdentity); |
| urq->result = UIL_ERR_LEN; |
| return result; |
| } |
| |
| /* Verify the user buffer. */ |
| result = verify_area(VERIFY_WRITE, urq->data, sizeof(lp->driverIdentity)); |
| if (result != 0) { |
| urq->result = UIL_FAILURE; |
| return result; |
| } |
| |
| /* Copy the driver identity into the user's buffer. */ |
| urq->result = UIL_SUCCESS; |
| copy_to_user(urq->data, &(lp->driverIdentity), sizeof(lp->driverIdentity)); |
| |
| return result; |
| } /* cfg_driver_identity */ |
| /*============================================================================*/ |
| |
| |
| #endif /* USE_UIL */ |
| |
| |
| /* If WIRELESS_EXT is not defined, then the functions that follow will not be |
| included in the build. */ |
| /* NOTE: Are these still even needed? */ |
| #ifdef WIRELESS_EXT |
| |
| |
| /******************************************************************************* |
| * wvlan_set_netname() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Set the ESSID of the card. |
| * |
| * PARAMETERS: |
| * |
| * wrq - a pointer to the wireless request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_set_netname(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| int ret = 0; |
| |
| wl_lock(lp, &flags); |
| |
| memset(lp->NetworkName, 0, sizeof(lp->NetworkName)); |
| memcpy(lp->NetworkName, extra, wrqu->data.length); |
| |
| /* Commit the adapter parameters */ |
| wl_apply(lp); |
| wl_unlock(lp, &flags); |
| |
| return ret; |
| } /* wvlan_set_netname */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_get_netname() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Get the ESSID of the card. |
| * |
| * PARAMETERS: |
| * |
| * wrq - a pointer to the wireless request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_get_netname(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| int ret = 0; |
| int status = -1; |
| wvName_t *pName; |
| |
| wl_lock(lp, &flags); |
| |
| /* Get the current network name */ |
| lp->ltvRecord.len = 1 + (sizeof(*pName) / sizeof(hcf_16)); |
| lp->ltvRecord.typ = CFG_CUR_SSID; |
| |
| status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord)); |
| |
| if (status == HCF_SUCCESS) { |
| pName = (wvName_t *)&(lp->ltvRecord.u.u32); |
| |
| memset(extra, '\0', HCF_MAX_NAME_LEN); |
| wrqu->data.length = pName->length; |
| |
| memcpy(extra, pName->name, pName->length); |
| } else { |
| ret = -EFAULT; |
| } |
| |
| wl_unlock(lp, &flags); |
| |
| return ret; |
| } /* wvlan_get_netname */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_set_station_nickname() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Set the card's station nickname. |
| * |
| * PARAMETERS: |
| * |
| * wrq - a pointer to the wireless request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_set_station_nickname(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| size_t len; |
| int ret = 0; |
| |
| wl_lock(lp, &flags); |
| |
| memset(lp->StationName, 0, sizeof(lp->StationName)); |
| len = min_t(size_t, wrqu->data.length, sizeof(lp->StationName)); |
| strlcpy(lp->StationName, extra, len); |
| |
| /* Commit the adapter parameters */ |
| wl_apply(lp); |
| wl_unlock(lp, &flags); |
| |
| return ret; |
| } /* wvlan_set_station_nickname */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_get_station_nickname() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Get the card's station nickname. |
| * |
| * PARAMETERS: |
| * |
| * wrq - a pointer to the wireless request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_get_station_nickname(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| int ret = 0; |
| int status = -1; |
| wvName_t *pName; |
| |
| wl_lock(lp, &flags); |
| |
| /* Get the current station name */ |
| lp->ltvRecord.len = 1 + (sizeof(*pName) / sizeof(hcf_16)); |
| lp->ltvRecord.typ = CFG_CNF_OWN_NAME; |
| |
| status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord)); |
| |
| if (status == HCF_SUCCESS) { |
| pName = (wvName_t *)&(lp->ltvRecord.u.u32); |
| |
| memset(extra, '\0', HCF_MAX_NAME_LEN); |
| wrqu->data.length = pName->length; |
| memcpy(extra, pName->name, pName->length); |
| } else { |
| ret = -EFAULT; |
| } |
| |
| wl_unlock(lp, &flags); |
| |
| /* out: */ |
| return ret; |
| } /* wvlan_get_station_nickname */ |
| /*============================================================================*/ |
| |
| |
| |
| |
| /******************************************************************************* |
| * wvlan_set_porttype() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Set the card's porttype |
| * |
| * PARAMETERS: |
| * |
| * wrq - a pointer to the wireless request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_set_porttype(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| int ret = 0; |
| hcf_16 portType; |
| |
| wl_lock(lp, &flags); |
| |
| /* Validate the new value */ |
| portType = *((__u32 *)extra); |
| |
| if (!((portType == 1) || (portType == 3))) { |
| ret = -EINVAL; |
| goto out_unlock; |
| } |
| |
| lp->PortType = portType; |
| |
| /* Commit the adapter parameters */ |
| wl_apply(lp); |
| |
| out_unlock: |
| wl_unlock(lp, &flags); |
| |
| /* out: */ |
| return ret; |
| } |
| |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wvlan_get_porttype() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Get the card's porttype |
| * |
| * PARAMETERS: |
| * |
| * wrq - a pointer to the wireless request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_get_porttype(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| int ret = 0; |
| int status = -1; |
| hcf_16 *pPortType; |
| __u32 *pData = (__u32 *)extra; |
| |
| wl_lock(lp, &flags); |
| |
| /* Get the current port type */ |
| lp->ltvRecord.len = 1 + (sizeof(*pPortType) / sizeof(hcf_16)); |
| lp->ltvRecord.typ = CFG_CNF_PORT_TYPE; |
| |
| status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord)); |
| |
| if (status == HCF_SUCCESS) { |
| pPortType = (hcf_16 *)&(lp->ltvRecord.u.u32); |
| |
| *pData = CNV_LITTLE_TO_INT(*pPortType); |
| } else { |
| ret = -EFAULT; |
| } |
| |
| wl_unlock(lp, &flags); |
| |
| /* out: */ |
| return ret; |
| } /* wvlan_get_porttype */ |
| /*============================================================================*/ |
| |
| #endif /* WIRELESS_EXT */ |
| |
| |
| |
| |
| #ifdef USE_RTS |
| /******************************************************************************* |
| * wvlan_rts() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * IOCTL handler for RTS commands |
| * |
| * PARAMETERS: |
| * |
| * rrq - a pointer to the rts request buffer |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * errno value otherwise |
| * |
| ******************************************************************************/ |
| int wvlan_rts(struct rtsreq *rrq, __u32 io_base) |
| { |
| int ioctl_ret = 0; |
| |
| DBG_PRINT("io_base: 0x%08x\n", io_base); |
| |
| switch (rrq->typ) { |
| case WL_IOCTL_RTS_READ: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_READ\n"); |
| rrq->data[0] = IN_PORT_WORD(io_base + rrq->reg); |
| DBG_TRACE(DbgInfo, " reg 0x%04x ==> 0x%04x\n", rrq->reg, CNV_LITTLE_TO_SHORT(rrq->data[0])); |
| break; |
| case WL_IOCTL_RTS_WRITE: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_WRITE\n"); |
| OUT_PORT_WORD(io_base + rrq->reg, rrq->data[0]); |
| DBG_TRACE(DbgInfo, " reg 0x%04x <== 0x%04x\n", rrq->reg, CNV_LITTLE_TO_SHORT(rrq->data[0])); |
| break; |
| case WL_IOCTL_RTS_BATCH_READ: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_BATCH_READ\n"); |
| IN_PORT_STRING_16(io_base + rrq->reg, rrq->data, rrq->len); |
| DBG_TRACE(DbgInfo, " reg 0x%04x ==> %d bytes\n", rrq->reg, rrq->len * sizeof(__u16)); |
| break; |
| case WL_IOCTL_RTS_BATCH_WRITE: |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_BATCH_WRITE\n"); |
| OUT_PORT_STRING_16(io_base + rrq->reg, rrq->data, rrq->len); |
| DBG_TRACE(DbgInfo, " reg 0x%04x <== %d bytes\n", rrq->reg, rrq->len * sizeof(__u16)); |
| break; |
| default: |
| |
| DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- UNSUPPORTED RTS CODE: 0x%X", rrq->typ); |
| ioctl_ret = -EOPNOTSUPP; |
| break; |
| } |
| |
| return ioctl_ret; |
| } /* wvlan_rts */ |
| /*============================================================================*/ |
| |
| #endif /* USE_RTS */ |