📄 sm_drv_ioctl_umac.c
字号:
essid.length = 0; scan_mode = SCAN_MODE_PASSIVE; } ret = sm_drv_oid_set(dev, DOT11_OID_SCANMODE, (void*)&scan_mode, sizeof(uint32_t)); if (ret < 0) return ret; ret = sm_drv_oid_set(dev, DOT11_OID_SCANSSID, (void*)&essid, sizeof(struct obj_ssid)); if (ret < 0) return ret; /* We let the background scanning work a bit...*/ if (scan_mode == SCAN_MODE_PASSIVE && lp->link_state != DOT11_STATE_ASSOC) msleep(2000); /* Let's start the scan timer in case UMAC doesn't trap the scan event */ mod_timer(&lp->scan_timer, jiffies + 4 * HZ); if (lp->link_state != DOT11_STATE_ASSOC && lp->bss_type != DOT11_BSSTYPE_IBSS) { ret = sm_drv_oid_set(dev, DOT11_OID_AUTOSCANDISABLE, (void*)&bgr_scan_disable, sizeof(uint32_t)); if (ret < 0) return ret; } /* And finally we send the scan request */ ret = sm_drv_oid_set(dev, DOT11_OID_SCAN, (void*)&scan, sizeof(int16_t)); if (ret < 0) { /* * If we're associated, we haven't disable bgr scan, * so we don't need to go there. */ if (lp->link_state != DOT11_STATE_ASSOC && lp->bss_type != DOT11_BSSTYPE_IBSS) goto scan_err_out; } return 0; scan_err_out: DEBUG(DBG_ALL, "Scanning failed (err: %d), turning background scanning on\n", ret); bgr_scan_disable = 0; sm_drv_oid_set(dev, DOT11_OID_AUTOSCANDISABLE, (void*)&bgr_scan_disable, sizeof(uint32_t)); return ret;}int sm_drv_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ int ret; char *current_ev = extra; DEBUG(DBG_IOCTL, "GET SCAN\n"); ret = sm_drv_parse_bssid(dev, NULL, 0, ¤t_ev); if (ret < 0) return ret; dwrq->length = (current_ev - extra); dwrq->flags = 0; return 0;}static int set_auth_order(struct net_device *dev, uint16_t flags){ uint8_t auth_order[4]; DEBUG(DBG_WPA, "AUTHORDER flags: 0x%x\n", flags); switch (flags) { case IW_AUTH_NOWPA: auth_order[0] = DOT11_AUTHALG_OS; auth_order[1] = DOT11_AUTHALG_SK; auth_order[2] = DOT11_AUTHALG_NONE; break; case IW_AUTH_WPA: DEBUG(DBG_WPA, "WPA authorder\n"); auth_order[0] = DOT11_AUTHALG_WPA; auth_order[1] = DOT11_AUTHALG_NONE; break; case IW_AUTH_WPA_PSK: DEBUG(DBG_WPA, "WPA_PSK authorder\n"); auth_order[0] = DOT11_AUTHALG_WPAPSK; auth_order[1] = DOT11_AUTHALG_NONE; break; case IW_AUTH_WPA2: DEBUG(DBG_WPA, "WPA2 authorder\n"); auth_order[0] = DOT11_AUTHALG_WPA2; auth_order[1] = DOT11_AUTHALG_NONE; break; case IW_AUTH_WPA2_PSK: DEBUG(DBG_WPA, "WPA2_PSK authorder\n"); auth_order[0] = DOT11_AUTHALG_WPA2PSK; auth_order[1] = DOT11_AUTHALG_NONE; break; default: printk("Using default authentication order\n"); auth_order[0] = DOT11_AUTHALG_OS; auth_order[1] = DOT11_AUTHALG_SK; auth_order[2] = DOT11_AUTHALG_NONE; break; } return sm_drv_oid_set(dev, DOT11_OID_AUTHORDER, (void*)auth_order, 4 * sizeof(uint8_t));}static int sm_drv_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ uint32_t ret; struct obj_ssid essid; DEBUG(DBG_IOCTL, "SET ESSID\n"); memset(essid.octets, 0, 33); /* Check if we were asked for `any' */ if (dwrq->flags && dwrq->length) { if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1)) return -E2BIG; essid.length = dwrq->length - 1; DEBUG(DBG_IOCTL, "New ESSID name: %s\n", extra); memcpy(essid.octets, extra, dwrq->length); } else essid.length = 0; ret = set_auth_order(dev, dwrq->flags & IW_AUTH_MASK); if (ret < 0) return ret; return sm_drv_oid_set(dev, DOT11_OID_SSID, (void*)&essid, sizeof(struct obj_ssid));}static int sm_drv_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct obj_ssid essid; int ret; DEBUG(DBG_IOCTL, "GET ESSID\n"); ret = sm_drv_oid_get(dev, DOT11_OID_SSID, (void*)&essid, sizeof(struct obj_ssid)); if (ret < 0) { extra = "\0"; return 0; } if (essid.length) { /* set ESSID to ON for Wireless Extensions */ dwrq->flags = 1; /* if it is to big, trunk it */ dwrq->length = min(IW_ESSID_MAX_SIZE, essid.length + 1); } else { dwrq->flags = 0; dwrq->length = 0; } essid.octets[essid.length] = '\0'; memcpy(extra, essid.octets, dwrq->length); return 0;}static int sm_drv_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ u32 rate; uint8_t data[17]; int ret, i; DEBUG(DBG_IOCTL, "SET RATE\n"); /* * First we need to get the supported rates */ ret = sm_drv_oid_get(dev, DOT11_OID_SUPPORTEDRATES, (void *)data, 17 * sizeof(uint8_t)); if (ret < 0) return ret; rate = (u32) (vwrq->value / 500000); i = 0; while (data[i]) { DEBUG(DBG_IOCTL, "rate[%d]->%d\n", i, data[i]); if (rate && (data[i] == rate)) { break; } if (vwrq->value == i) { break; } data[i] |= 0x80; i++; } if (!data[i]) return -EINVAL; data[i] |= 0x80; data[i + 1] = 0; /* Now, check if we want a fixed or auto value */ if (vwrq->fixed) { data[0] = data[i]; data[1] = 0; } ret = sm_drv_oid_set(dev, DOT11_OID_EXTENDEDRATES, (void *)data, 17 * sizeof(uint8_t)); if (ret < 0) return ret; ret = sm_drv_oid_set(dev, DOT11_OID_RATES, (void *)data, 17 * sizeof(uint8_t)); if (ret < 0) return ret; return -EINPROGRESS;}/* Get the current bit rate */static int sm_drv_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret; uint32_t state; DEBUG(DBG_IOCTL, "GET RATE\n"); /* Get the current bit rate */ ret = sm_drv_oid_get(dev, GEN_OID_LINKSTATE, (void *)&state, sizeof(uint32_t)); if (ret < 0) return ret; vwrq->value = state * 500000; vwrq->fixed = 1; return 0;}static int sm_drv_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ DEBUG(DBG_IOCTL, "SET RTS\n"); return sm_drv_oid_set(dev, DOT11_OID_RTSTHRESH, (void*)&vwrq->value, sizeof(uint32_t));}static int sm_drv_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ uint32_t rts, ret; DEBUG(DBG_IOCTL, "SET RTS\n"); /* get the rts threshold */ ret = sm_drv_oid_get(dev, DOT11_OID_RTSTHRESH, (void *)&rts, sizeof(uint32_t)); if (ret < 0) return ret; vwrq->value = rts; return ret;}static int sm_drv_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ DEBUG(DBG_IOCTL, "SET RTS\n"); return sm_drv_oid_set(dev, DOT11_OID_FRAGTHRESH, (void*)&vwrq->value, sizeof(uint32_t));}static int sm_drv_get_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ uint32_t frag, ret; DEBUG(DBG_IOCTL, "SET RTS\n"); /* get the rts threshold */ ret = sm_drv_oid_get(dev, DOT11_OID_FRAGTHRESH, (void *)&frag, sizeof(uint32_t)); if (ret < 0) return ret; vwrq->value = frag; return ret;}static int sm_drv_set_txpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ uint32_t output_power = vwrq->value; DEBUG(DBG_IOCTL, "SET TXPOWER\n"); /* Conexant firmware operates in 1/4 dBm */ output_power *= 4; if (vwrq->disabled) { DEBUG(DBG_ALL, "Radio OFF not supported\n"); return 0; //return sm_drv_oid_set(dev, GEN_OID_HIBERNATE, (void*)&radio_on, sizeof(uint32_t)); } else if (vwrq->fixed) {// printk("Setting TX output power to %d dBm\n", output_power/4); return sm_drv_oid_set(dev, DOT11_OID_OUTPUTPOWER, (void *)&output_power, sizeof(uint32_t)); } else { DEBUG(DBG_IOCTL, "Radio is ON\n"); return 0; //return sm_drv_oid_set(dev, GEN_OID_HIBERNATE, (void*)&radio_on, sizeof(uint32_t)); }}static int sm_drv_get_txpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret; uint32_t output_power; DEBUG(DBG_IOCTL, "GET TXPOWER\n"); ret = sm_drv_oid_get(dev, DOT11_OID_OUTPUTPOWER, (void *)&output_power, sizeof(uint32_t)); if (ret < 0) return ret; /* Conexant firmware operates in 0.25 dBm (1/4 dBm) */ vwrq->value = output_power/4; vwrq->fixed = 1; /* * Radio is not turned off * btw: how is possible to turn off only the radio */ vwrq->disabled = 0; return ret;}static int sm_drv_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ int ret = 0, force = 0; int invoke = 0, exunencrypt = 0; DEBUG(DBG_IOCTL, "SET ENCODE\n"); /* * With the new API, it's impossible to get a NULL pointer. * New version of iwconfig set the IW_ENCODE_NOKEY flag * when no key is given, but older versions don't. */ if (dwrq->length > 0) { /* we have a key to set */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int current_index; struct obj_key key = {DOT11_PRIV_WEP, 0, ""}; /* get the current key index */ ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID, (void *)¤t_index, sizeof(uint32_t)); if (ret < 0) return ret; /* Verify that the key is not marked as invalid */ if (!(dwrq->flags & IW_ENCODE_NOKEY)) { key.length = dwrq->length > sizeof (key.key) ? sizeof (key.key) : dwrq->length; memcpy(key.key, extra, key.length); if ((index < 0) || (index > 3)) /* no index provided use the current one */ index = current_index; /* now send the key to the card */ ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID + index + 1, (void *)&key, sizeof(struct obj_key)); if (ret < 0) return ret; } /* * If a valid key is set, encryption should be enabled * (user may turn it off later). * This is also how "iwconfig ethX key on" works */ if ((index == current_index) && (key.length > 0)) force = 1; } else { int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; struct obj_key key = {DOT11_PRIV_WEP, 0, ""}; if ((index >= 0) && (index <= 3)) { /* we want to set the key index */ ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID, (void *)&index, sizeof(uint32_t)); if (ret < 0) return ret; ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID + index + 1, (void *)&key, sizeof(struct obj_key)); if (ret < 0) return ret; /* We have a key there, let's turn encryption on */ if (key.length > 0) force = 1; } else { if (!dwrq->flags & IW_ENCODE_MODE) { /* we cannot do anything. Complain. */ return -EINVAL; } } } /* now read the flags */ if (dwrq->flags & IW_ENCODE_DISABLED) { /* Encoding disabled, * authen = DOT11_AUTH_OS; * invoke = 0; * exunencrypt = 0; */ } if (dwrq->flags & IW_ENCODE_OPEN) /* Encode but accept non-encoded packets. No auth */ invoke = 1; if ((dwrq->flags & IW_ENCODE_RESTRICTED) || force) { /* Refuse non-encoded packets. Auth */ invoke = 1; exunencrypt = 1; } /* do the change if requested */ if ((dwrq->flags & IW_ENCODE_MODE) || force) { ret = sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED, (void *)&invoke, sizeof(uint32_t)); ret |= sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED, (void *)&exunencrypt, sizeof(uint32_t)); } return ret;}static int sm_drv_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct obj_key key; u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1; uint32_t authen = 0, invoke = 0, exunencrypt = 0; int ret; DEBUG(DBG_IOCTL, "GET ENCODE\n"); /* first get the flags */ ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE, (void *)&authen, sizeof(uint32_t)); ret |= sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED, (void *)&invoke, sizeof(uint32_t)); ret |= sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED, (void *)&exunencrypt, sizeof(uint32_t)); if (ret < 0) return ret; if (invoke && ((authen == DOT11_AUTH_OS) || (authen == DOT11_AUTH_BOTH)) && exunencrypt) { switch (invoke) { case DOT11_PRIV_INV_WEP: dwrq->flags = IW_ENCODE_RESTRICTED; break; case DOT11_PRIV_INV_TKIP: dwrq->flags |= IW_ENCODE_TKIP; break; case DOT11_PRIV_INV_AES_CCMP: dwrq->flags |= IW_ENCODE_AES; break; } } else if (((authen == DOT11_AUTH_OS) || (authen == DOT11_AUTH_BOTH)) && !exunencrypt) { /* If we set it to DISABLED, we won't see the keys */ dwrq->flags = IW_ENCODE_OPEN; } else /* The card should not work in this state */ dwrq->flags = 0; /* get the current device key index */ ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID, (void *)&devindex, sizeof(uint32_t)); if (ret < 0) return ret; if ((index < 0) || (index > 3)) /* no index provided, use the current one */ index = devindex; ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID + index + 1, (void *)&key, sizeof(struct obj_key)); if (ret < 0) return ret; dwrq->length = key.length; memcpy(extra, key.key, dwrq->length); /* return the used key index */ dwrq->flags |= devindex + 1; return ret;}static int sm_drv_set_ps(struct net_device *dev, struct iw_request_info *info, struct iw_param *prq, char * extra){ uint32_t psm; DEBUG(DBG_IOCTL, "SET PSM\n"); if (prq->disabled) { printk("No power saving\n"); psm = DOT11_PSM_ACTIVE; } else { switch (prq->flags & IW_POWER_MODE) { case IW_POWER_ALL_R: psm = DOT11_PSM_POWERSAVE; printk("Full PSM\n"); break; default: psm = DOT11_PSM_DYNAMIC; printk("Dynamic PSM\n"); } if (prq->value) { uint32_t cam_timeout = prq->value; int ret; ret = sm_drv_oid_set(dev, DOT11_OID_CAMTIMEOUT, (void *)&cam_timeout, sizeof(uint32_t)); if (ret < 0) return ret; printk("PSM timeout %d ms\n", cam_timeout); } } return sm_drv_oid_set(dev, DOT11_OID_PSM, (void *)&psm, sizeof(uint32_t));}static int sm_drv_get_ps(struct net_device *dev, struct iw_request_info *info, struct iw_param *prq, char * extra){ int ret = 0; uint32_t psm, cam_timeout; DEBUG(DBG_IOCTL, "GET PSM\n"); ret = sm_drv_oid_get(dev, DOT11_OID_PSM, (void *)&psm, sizeof(uint32_t)); if (ret < 0) return ret; ret = sm_drv_oid_get(dev, DOT11_OID_CAMTIMEOUT, (void *)&cam_timeout, sizeof(uint32_t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -