1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: implementation of the driver FTM functions interfacing with linux kernel 21 */ 22 23 #include <qdf_util.h> 24 #include <wlan_objmgr_pdev_obj.h> 25 #include <wlan_ftm_ucfg_api.h> 26 #include <qdf_types.h> 27 #include <qdf_module.h> 28 #include <wlan_cfg80211_ftm.h> 29 #include <wlan_ioctl_ftm.h> 30 31 static QDF_STATUS 32 wlan_process_ftm_ioctl_cmd(struct wlan_objmgr_pdev *pdev, 33 uint8_t *userdata, uint32_t length) 34 { 35 uint8_t *buffer; 36 QDF_STATUS error; 37 38 if (get_user(length, (uint32_t *)userdata) != 0) 39 return QDF_STATUS_E_FAILURE; 40 41 if (length > WLAN_FTM_DATA_MAX_LEN) 42 return QDF_STATUS_E_FAILURE; 43 44 buffer = qdf_mem_malloc(length); 45 if (!buffer) 46 return QDF_STATUS_E_NOMEM; 47 48 if (copy_from_user(buffer, &userdata[sizeof(length)], length)) 49 error = QDF_STATUS_E_FAILURE; 50 else 51 error = ucfg_wlan_ftm_testmode_cmd(pdev, buffer, length); 52 53 qdf_mem_free(buffer); 54 55 return error; 56 } 57 58 static QDF_STATUS 59 wlan_process_ftm_ioctl_rsp(struct wlan_objmgr_pdev *pdev, 60 uint8_t *userdata, uint32_t length) 61 { 62 uint8_t *buffer; 63 QDF_STATUS error; 64 65 length = WLAN_FTM_DATA_MAX_LEN + sizeof(u_int32_t); 66 67 buffer = qdf_mem_malloc(length); 68 if (!buffer) 69 return QDF_STATUS_E_NOMEM; 70 71 error = ucfg_wlan_ftm_testmode_rsp(pdev, buffer); 72 if (!error) 73 error = copy_to_user((userdata - sizeof(int)), buffer, length); 74 else 75 error = QDF_STATUS_E_AGAIN; 76 77 qdf_mem_free(buffer); 78 79 return error; 80 } 81 82 int 83 wlan_ioctl_ftm_testmode_cmd(struct wlan_objmgr_pdev *pdev, int cmd, 84 uint8_t *userdata, uint32_t length) 85 { 86 QDF_STATUS error; 87 struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj; 88 89 ftm_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 90 WLAN_UMAC_COMP_FTM); 91 if (!ftm_pdev_obj) { 92 ftm_err("Failed to get ftm pdev component"); 93 return QDF_STATUS_E_FAILURE; 94 } 95 96 ftm_pdev_obj->cmd_type = WIFI_FTM_CMD_IOCTL; 97 98 switch (cmd) { 99 case FTM_IOCTL_UNIFIED_UTF_CMD: 100 error = wlan_process_ftm_ioctl_cmd(pdev, 101 userdata, length); 102 break; 103 case FTM_IOCTL_UNIFIED_UTF_RSP: 104 error = wlan_process_ftm_ioctl_rsp(pdev, 105 userdata, length); 106 break; 107 default: 108 ftm_err("FTM Unknown cmd - not supported"); 109 error = QDF_STATUS_E_NOSUPPORT; 110 } 111 112 return qdf_status_to_os_return(error); 113 } 114 115 qdf_export_symbol(wlan_ioctl_ftm_testmode_cmd); 116