📄 sample_pm.c
字号:
/* Note : this particular snipset of code is available under * the LGPL, MPL or BSD license (at your choice). * Jean II *//* --------------------------- INCLUDE --------------------------- *//* Backward compatibility for Wireless Extension 9 */#ifndef IW_POWER_MODIFIER#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */#define IW_POWER_MIN 0x0001 /* Value is a minimum */#define IW_POWER_MAX 0x0002 /* Value is a maximum */#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */#endif IW_POWER_MODIFIERstruct net_local { int pm_on; // Power Management enabled int pm_multi; // Receive multicasts int pm_period; // Power Management period int pm_period_auto; // Power Management auto mode int pm_max_period; // Power Management max period int pm_min_period; // Power Management min period int pm_timeout; // Power Management timeout};/* --------------------------- HANDLERS --------------------------- */static int ioctl_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *prq, char *extra){ /* Disable it ? */ if(prq->disabled) { local->pm_on = 0; } else { /* Check mode */ switch(prq->flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: local->pm_multi = 0; local->need_commit = 1; break; case IW_POWER_ALL_R: local->pm_multi = 1; local->need_commit = 1; break; case IW_POWER_ON: /* None = ok */ break; default: /* Invalid */ return(-EINVAL); } /* Set period */ if(prq->flags & IW_POWER_PERIOD) { int period = prq->value/1000000; /* Hum: check if within bounds... */ /* Activate PM */ local->pm_on = 1; local->need_commit = 1; /* Check min value */ if(prq->flags & IW_POWER_MIN) { local->pm_min_period = period; local->pm_period_auto = 1; } else /* Check max value */ if(prq->flags & IW_POWER_MAX) { local->pm_max_period = period; local->pm_period_auto = 1; } else { /* Fixed value */ local->pm_period = period; local->pm_period_auto = 0; } } /* Set timeout */ if(prq->flags & IW_POWER_TIMEOUT) { /* Activate PM */ local->pm_on = 1; local->need_commit = 1; /* Fixed value in ms */ local->pm_timeout = prq->value/1000; } } return(0);}static int ioctl_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *prq, char *extra){ prq->disabled = !local->pm_on; /* By default, display the period */ if(!(prq->flags & IW_POWER_TIMEOUT)) { int inc_flags = prq->flags; prq->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; /* Check if auto */ if(local->pm_period_auto) { /* By default, the min */ if(!(inc_flags & IW_POWER_MAX)) { prq->value = local->pm_min_period * 1000000; prq->flags |= IW_POWER_MIN; } else { prq->value = local->pm_max_period * 1000000; prq->flags |= IW_POWER_MAX; } } else { /* Fixed value. Check the flags */ if(inc_flags & (IW_POWER_MIN | IW_POWER_MAX)) return(-EINVAL); else prq->value = local->pm_period * 1000000; } } else { /* Deal with the timeout - always fixed */ prq->flags = IW_POWER_TIMEOUT; prq->value = local->pm_timeout * 1000; } if(local->pm_multi) prq->flags |= IW_POWER_ALL_R; else prq->flags |= IW_POWER_UNICAST_R; return(0);}static int ioctl_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *rrq, char *extra){ struct iw_range *range = (struct iw_range *) extra; rrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range));#if WIRELESS_EXT > 10 /* Version we are compiled with */ range->we_version_compiled = WIRELESS_EXT; /* Minimum version we recommend */ range->we_version_source = 8;#endif /* WIRELESS_EXT > 10 */#if WIRELESS_EXT > 9 range.min_pmp = 1000000; /* 1 units */ range.max_pmp = 12000000; /* 12 units */ range.min_pmt = 1000; /* 1 ms */ range.max_pmt = 1000000; /* 1 s */ range.pmp_flags = IW_POWER_PERIOD | IW_POWER_RELATIVE | IW_POWER_MIN | IW_POWER_MAX; range.pmt_flags = IW_POWER_TIMEOUT; range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;#endif /* WIRELESS_EXT > 9 */ return(0);}/* --------------------------- BINDING --------------------------- */#if WIRELESS_EXT > 12/* Use the new driver API, save overhead */static const iw_handler handler_table[] ={ ... (iw_handler) ioctl_set_power, /* SIOCSIWPOWER */ (iw_handler) ioctl_get_power, /* SIOCGIWPOWER */};#else /* WIRELESS_EXT < 12 *//* Use old API in the ioctl handler */static intdo_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){ struct iwreq *wrq = (struct iwreq *) ifr; int err = 0; switch (cmd) {#if WIRELESS_EXT > 8 /* Set the desired Power Management mode */ case SIOCSIWPOWER: err = ioctl_set_power(dev, NULL, &(wrq->u.power), NULL); break; /* Get the power management settings */ case SIOCGIWPOWER: err = ioctl_get_power(dev, NULL, &(wrq->u.power), NULL); break;#endif /* WIRELESS_EXT > 8 */ } return(err);}#endif /* WIRELESS_EXT < 12 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -