/** * __wcnss_debugfs_open() - open debugfs * @inode: inode pointer * @file: file pointer * * Return: 0 on success, error number otherwise */ static int __wcnss_debugfs_open(struct inode *inode, struct file *file) { hdd_adapter_t *adapter; hdd_context_t *hdd_ctx; int ret; ENTER(); if (inode->i_private) file->private_data = inode->i_private; adapter = (hdd_adapter_t *)file->private_data; if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", __func__); return -EINVAL; } hdd_ctx = WLAN_HDD_GET_CTX(adapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; EXIT(); return 0; }
/**-------------------------------------------------------------------------------------------- \brief __iw_get_oem_data_rsp() - This function gets the oem data response. This invokes the respective sme functionality. Function for handling the oem data rsp IOCTL \param - dev - Pointer to the net device - info - Pointer to the iw_oem_data_req - wrqu - Pointer to the iwreq data - extra - Pointer to the data \return - 0 for success, non zero for failure -----------------------------------------------------------------------------------------------*/ int __iw_get_oem_data_rsp( struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { int rc = 0; eHalStatus status; struct iw_oem_data_rsp* pHddOemDataRsp; tOemDataRsp* pSmeOemDataRsp; hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx; ENTER(); pAdapter = (netdev_priv(dev)); if (NULL == pAdapter) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL",__func__); return -EINVAL; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); rc = wlan_hdd_validate_context(pHddCtx); if (0 != rc) { return rc; } do { //get the oem data response from sme status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp); if (status != eHAL_STATUS_SUCCESS) { hddLog(LOGE, "%s: failed in sme_getOemDataRsp", __func__); rc = -EIO; break; } else { if (pSmeOemDataRsp != NULL) { pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra); vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); } else { hddLog(LOGE, "%s: pSmeOemDataRsp = NULL", __func__); rc = -EIO; break; } } } while(0); EXIT(); return rc; }
/**-------------------------------------------------------------------------------------------- \brief __iw_set_oem_data_req() - This function sets the oem data req configuration. This invokes the respective sme oem data req functionality. Function for handling the set IOCTL for the oem data req configuration \param - dev - Pointer to the net device - info - Pointer to the iw_oem_data_req - wrqu - Pointer to the iwreq data - extra - Pointer to the data \return - 0 for success, non zero for failure -----------------------------------------------------------------------------------------------*/ int __iw_set_oem_data_req( struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { int rc = 0; eHalStatus status = eHAL_STATUS_SUCCESS; struct iw_oem_data_req *pOemDataReq = NULL; tOemDataReqConfig oemDataReqConfig; tANI_U32 oemDataReqID = 0; hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx; hdd_wext_state_t *pwextBuf; ENTER(); pAdapter = (netdev_priv(dev)); if (NULL == pAdapter) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL",__func__); return -EINVAL; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); rc = wlan_hdd_validate_context(pHddCtx); if (0 != rc) { return rc; } pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); if (NULL == pwextBuf) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: pwextBuf is NULL",__func__); return -EINVAL; } do { if (NULL != wrqu->data.pointer) { pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer; } if (pOemDataReq == NULL) { hddLog(LOGE, "in %s oemDataReq == NULL", __func__); rc = -EIO; break; } vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig)); if (copy_from_user((&oemDataReqConfig)->oemDataReq, pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: copy_from_user() failed!", __func__); rc = -EFAULT; break; } status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &oemDataReqConfig, &oemDataReqID, &hdd_OemDataReqCallback, dev); if (status != eHAL_STATUS_SUCCESS) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_OemDataReq status %d", __func__, status); rc = -EFAULT; break; } pwextBuf->oemDataReqID = oemDataReqID; pwextBuf->oemDataReqInProgress = TRUE; } while(0); EXIT(); return rc; }
/** * __iw_get_scan() - get scan results * @dev: Pointer to the net device. * @info: Pointer to the iw_request_info. * @wrqu: Pointer to the iwreq_data. * @extra: Pointer to the data. * * This function returns the scan results to the wpa_supplicant * * Return: 0 on success, error number otherwise */ static int __iw_get_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); tCsrScanResultInfo *pScanResult; eHalStatus status = eHAL_STATUS_SUCCESS; hdd_scan_info_t scanInfo; tScanResultHandle pResult; int i = 0; hdd_context_t *hdd_ctx; int ret; ENTER(); hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!", __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA); if (TRUE == pAdapter->scan_info.mScanPending) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__); return -EAGAIN; } scanInfo.dev = dev; scanInfo.start = extra; scanInfo.info = info; if (0 == wrqu->data.length) { scanInfo.end = extra + IW_SCAN_MAX_DATA; } else { scanInfo.end = extra + wrqu->data.length; } status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult); if (NULL == pResult) { // no scan results hddLog(LOG1,"iw_get_scan: NULL Scan Result "); return 0; } pScanResult = sme_ScanResultGetFirst(hHal, pResult); while (pScanResult) { status = hdd_IndicateScanResult(&scanInfo, pScanResult); if (0 != status) { break; } i++; pScanResult = sme_ScanResultGetNext(hHal, pResult); } sme_ScanResultPurge(hHal, pResult); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i); EXIT(); return status; }
/** * __iw_set_scan() - set scan request * @dev: Pointer to the net device. * @info: Pointer to the iw_request_info. * @wrqu: Pointer to the iwreq_data. * @extra: Pointer to the data. * * This function process the scan request from the wpa_supplicant * and set the scan request to the SME * * Return: 0 on success, error number otherwise */ static int __iw_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrScanRequest scanRequest; v_U32_t scanId = 0; eHalStatus status = eHAL_STATUS_SUCCESS; struct iw_scan_req *scanReq = (struct iw_scan_req *)extra; hdd_adapter_t *con_sap_adapter; uint16_t con_dfs_ch; int ret; ENTER(); ret = wlan_hdd_validate_context(pHddCtx); if (0 != ret) return ret; /* Block All Scan during DFS operation and send null scan result */ con_sap_adapter = hdd_get_con_sap_adapter(pAdapter, true); if (con_sap_adapter) { con_dfs_ch = con_sap_adapter->sessionCtx.ap.operatingChannel; if (VOS_IS_DFS_CH(con_dfs_ch)) { hddLog(LOGW, "%s:##In DFS Master mode. Scan aborted", __func__); return -EOPNOTSUPP; } } if(pAdapter->scan_info.mScanPending == TRUE) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__); return eHAL_STATUS_SUCCESS; } vos_mem_zero( &scanRequest, sizeof(scanRequest)); if (NULL != wrqu->data.pointer) { /* set scanType, active or passive */ if ((IW_SCAN_TYPE_ACTIVE == scanReq->scan_type) || (eSIR_ACTIVE_SCAN == pHddCtx->ioctl_scan_mode)) { scanRequest.scanType = eSIR_ACTIVE_SCAN; } else { scanRequest.scanType = eSIR_PASSIVE_SCAN; } /* set bssid using sockaddr from iw_scan_req */ vos_mem_copy(scanRequest.bssid, &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) ); if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { if(scanReq->essid_len && (scanReq->essid_len <= SIR_MAC_MAX_SSID_LENGTH)) { scanRequest.SSIDs.numOfSSIDs = 1; scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo)); if(scanRequest.SSIDs.SSIDList) { scanRequest.SSIDs.SSIDList->SSID.length = scanReq->essid_len; vos_mem_copy(scanRequest.SSIDs.SSIDList-> SSID.ssId,scanReq->essid,scanReq->essid_len); } else { scanRequest.SSIDs.numOfSSIDs = 0; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__); VOS_ASSERT(0); } } else { hddLog(LOGE, FL("Invalid essid length : %d"), scanReq->essid_len); } } /* set min and max channel time */ scanRequest.minChnTime = scanReq->min_channel_time; scanRequest.maxChnTime = scanReq->max_channel_time; } else { if (pHddCtx->ioctl_scan_mode == eSIR_ACTIVE_SCAN) { /* set the scan type to active */ scanRequest.scanType = eSIR_ACTIVE_SCAN; } else { scanRequest.scanType = eSIR_PASSIVE_SCAN; } vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff ); /* set min and max channel time to zero */ scanRequest.minChnTime = 0; scanRequest.maxChnTime = 0; } /* set BSSType to default type */ scanRequest.BSSType = eCSR_BSS_TYPE_ANY; /*Scan all the channels */ scanRequest.ChannelInfo.numOfChannels = 0; scanRequest.ChannelInfo.ChannelList = NULL; /* set requestType to full scan */ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; /* if previous genIE is not NULL, update ScanIE */ if (0 != pwextBuf->genIE.length) { memset( &pAdapter->scan_info.scanAddIE, 0, sizeof(pAdapter->scan_info.scanAddIE) ); memcpy( pAdapter->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, pwextBuf->genIE.length ); pAdapter->scan_info.scanAddIE.length = pwextBuf->genIE.length; pwextBuf->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata; pwextBuf->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length; /* clear previous genIE after use it */ memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) ); } /* push addIEScan in scanRequset if exist */ if (pAdapter->scan_info.scanAddIE.addIEdata && pAdapter->scan_info.scanAddIE.length) { scanRequest.uIEFieldLen = pAdapter->scan_info.scanAddIE.length; scanRequest.pIEField = pAdapter->scan_info.scanAddIE.addIEdata; } status = sme_ScanRequest((WLAN_HDD_GET_CTX(pAdapter))->hHal, pAdapter->sessionId, &scanRequest, &scanId, &hdd_ScanRequestCallback, dev); if (!HAL_STATUS_SUCCESS(status)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest fail %d!!!",__func__, status); goto error; } pAdapter->scan_info.mScanPending = TRUE; pAdapter->scan_info.scanId = scanId; error: if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len)) vos_mem_free(scanRequest.SSIDs.SSIDList); EXIT(); return status; }
/** * __wcnss_wowenable_write() - write wow enable * @file: file pointer * @buf: buffer * @count: count * @ppos: position pointer * * Return: 0 on success, error number otherwise */ static ssize_t __wcnss_wowenable_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { hdd_adapter_t *pAdapter; hdd_context_t *hdd_ctx; char cmd[MAX_USER_COMMAND_SIZE_WOWL_ENABLE + 1]; char *sptr, *token; v_U8_t wow_enable = 0; v_U8_t wow_mp = 0; v_U8_t wow_pbm = 0; int ret; ENTER(); pAdapter = (hdd_adapter_t *)file->private_data; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", __func__); return -EINVAL; } hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; if (!sme_IsFeatureSupportedByFW(WOW)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Wake-on-Wireless feature is not supported " "in firmware!", __func__); return -EINVAL; } if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Command length is larger than %d bytes.", __func__, MAX_USER_COMMAND_SIZE_WOWL_ENABLE); return -EINVAL; } /* Get command from user */ if (copy_from_user(cmd, buf, count)) return -EFAULT; cmd[count] = '\0'; sptr = cmd; /* Get enable or disable wow */ token = strsep(&sptr, " "); if (!token) return -EINVAL; if (kstrtou8(token, 0, &wow_enable)) return -EINVAL; /* Disable wow */ if (!wow_enable) { if (!hdd_exit_wowl(pAdapter)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: hdd_exit_wowl failed!", __func__); return -EFAULT; } return count; } /* Get enable or disable magic packet mode */ token = strsep(&sptr, " "); if (!token) return -EINVAL; if (kstrtou8(token, 0, &wow_mp)) return -EINVAL; if (wow_mp > 1) wow_mp = 1; /* Get enable or disable pattern byte matching mode */ token = strsep(&sptr, " "); if (!token) return -EINVAL; if (kstrtou8(token, 0, &wow_pbm)) return -EINVAL; if (wow_pbm > 1) wow_pbm = 1; if (!hdd_enter_wowl(pAdapter, wow_mp, wow_pbm)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: hdd_enter_wowl failed!", __func__); return -EFAULT; } EXIT(); return count; }
/** * __wcnss_patterngen_write() - write pattern * @file: file pointer * @buf: buffer * @count: count * @ppos: position pointer * * Return: 0 on success, error number otherwise */ static ssize_t __wcnss_patterngen_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx; tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams; tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams; char *cmd, *sptr, *token; v_U8_t pattern_idx = 0; v_U8_t pattern_duration = 0; char *pattern_buf; v_U16_t pattern_len = 0; v_U16_t i = 0; int ret; ENTER(); pAdapter = (hdd_adapter_t *)file->private_data; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", __func__); return -EINVAL; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); if (0 != ret) return ret; if (!sme_IsFeatureSupportedByFW(WLAN_PERIODIC_TX_PTRN)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Periodic Tx Pattern Offload feature is not supported " "in firmware!", __func__); return -EINVAL; } /* Get command from user */ if (count <= MAX_USER_COMMAND_SIZE_FRAME) cmd = vos_mem_malloc(count + 1); else { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Command length is larger than %d bytes.", __func__, MAX_USER_COMMAND_SIZE_FRAME); return -EINVAL; } if (!cmd) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for cmd failed!", __func__); return -EFAULT; } if (copy_from_user(cmd, buf, count)) { vos_mem_free(cmd); return -EFAULT; } cmd[count] = '\0'; sptr = cmd; /* Get pattern idx */ token = strsep(&sptr, " "); if (!token) goto failure; if (kstrtou8(token, 0, &pattern_idx)) goto failure; if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Pattern index %d is not in the range (0 ~ %d).", __func__, pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1); goto failure; } /* Get pattern duration */ token = strsep(&sptr, " "); if (!token) goto failure; if (kstrtou8(token, 0, &pattern_duration)) goto failure; /* Delete pattern using index if duration is 0 */ if (!pattern_duration) { delPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirDelPeriodicTxPtrn)); if (!delPeriodicTxPtrnParams) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for delPeriodicTxPtrnParams " "failed!", __func__); vos_mem_free(cmd); return -EFAULT; } delPeriodicTxPtrnParams->ucPtrnId = pattern_idx; delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx; vos_mem_copy(delPeriodicTxPtrnParams->macAddress, pAdapter->macAddressCurrent.bytes, 6); /* Delete pattern */ if (eHAL_STATUS_SUCCESS != sme_DelPeriodicTxPtrn(pHddCtx->hHal, delPeriodicTxPtrnParams)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_DelPeriodicTxPtrn() failed!", __func__); vos_mem_free(delPeriodicTxPtrnParams); goto failure; } vos_mem_free(cmd); vos_mem_free(delPeriodicTxPtrnParams); return count; } /* Check if it's in connected state only when adding patterns */ if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Not in Connected state!", __func__); goto failure; } /* Get pattern */ token = strsep(&sptr, " "); if (!token) goto failure; pattern_buf = token; pattern_buf[strlen(pattern_buf) - 1] = '\0'; pattern_len = strlen(pattern_buf); /* Since the pattern is a hex string, 2 characters represent 1 byte. */ if (pattern_len % 2) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Malformed pattern!", __func__); goto failure; } else pattern_len >>= 1; if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Not an 802.3 frame!", __func__); goto failure; } addPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirAddPeriodicTxPtrn)); if (!addPeriodicTxPtrnParams) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for addPeriodicTxPtrnParams " "failed!", __func__); vos_mem_free(cmd); return -EFAULT; } addPeriodicTxPtrnParams->ucPtrnId = pattern_idx; addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500; addPeriodicTxPtrnParams->ucPtrnSize = pattern_len; vos_mem_copy(addPeriodicTxPtrnParams->macAddress, pAdapter->macAddressCurrent.bytes, 6); /* Extract the pattern */ for(i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) { addPeriodicTxPtrnParams->ucPattern[i] = (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]); /* Skip to next byte */ pattern_buf += 2; } /* Add pattern */ if (eHAL_STATUS_SUCCESS != sme_AddPeriodicTxPtrn(pHddCtx->hHal, addPeriodicTxPtrnParams)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_AddPeriodicTxPtrn() failed!", __func__); vos_mem_free(addPeriodicTxPtrnParams); goto failure; } vos_mem_free(cmd); vos_mem_free(addPeriodicTxPtrnParams); EXIT(); return count; failure: vos_mem_free(cmd); return -EINVAL; }
/** * __wcnss_wowpattern_write() - write wow pattern * @file: file pointer * @buf: buffer * @count: count * @ppos: position pointer * * Return: 0 on success, error number otherwise */ static ssize_t __wcnss_wowpattern_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data; hdd_context_t *hdd_ctx; char cmd[MAX_USER_COMMAND_SIZE_WOWL_PATTERN + 1]; char *sptr, *token; v_U8_t pattern_idx = 0; v_U8_t pattern_offset = 0; char *pattern_buf; char *pattern_mask; int ret; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", __func__); return -EINVAL; } hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; if (!sme_IsFeatureSupportedByFW(WOW)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Wake-on-Wireless feature is not supported " "in firmware!", __func__); return -EINVAL; } if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Command length is larger than %d bytes.", __func__, MAX_USER_COMMAND_SIZE_WOWL_PATTERN); return -EINVAL; } /* Get command from user */ if (copy_from_user(cmd, buf, count)) return -EFAULT; cmd[count] = '\0'; sptr = cmd; /* Get pattern idx */ token = strsep(&sptr, " "); if (!token) return -EINVAL; if (kstrtou8(token, 0, &pattern_idx)) return -EINVAL; /* Get pattern offset */ token = strsep(&sptr, " "); /* Delete pattern if no further argument */ if (!token) { hdd_del_wowl_ptrn_debugfs(pAdapter, pattern_idx); return count; } if (kstrtou8(token, 0, &pattern_offset)) return -EINVAL; /* Get pattern */ token = strsep(&sptr, " "); if (!token) return -EINVAL; pattern_buf = token; /* Get pattern mask */ token = strsep(&sptr, " "); if (!token) return -EINVAL; pattern_mask = token; pattern_mask[strlen(pattern_mask) - 1] = '\0'; hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset, pattern_buf, pattern_mask); EXIT(); return count; }