staticstruct p54_rssi_db_entry p54_rssi_default = { /* * The defaults are taken from usb-logs of the * vendor driver. So, they should be safe to * use in case we can't get a match from the * rssi <-> dBm conversion database.
*/
.mul = 130,
.add = -398,
};
/* * usually all lists in the eeprom are mostly sorted. * so it's very likely that the entry we are looking for * is right at the end of the list
*/ for (i = list->entries; i >= 0; i--) { if (freq == list->channels[i].freq) {
entry = &list->channels[i]; break;
}
}
if ((i < 0) && (list->entries < list->max_entries)) { /* entry does not exist yet. Initialize a new one. */ int band = p54_get_band_from_freq(freq);
/* * filter out frequencies which don't belong into * any supported band.
*/ if (band >= 0) {
i = list->entries++;
list->band_channel_num[band]++;
case PDR_SYNTH_FRONTEND_DUETTE3: case PDR_SYNTH_FRONTEND_DUETTE2: case PDR_SYNTH_FRONTEND_FRISBEE: case PDR_SYNTH_FRONTEND_XBOW: { struct pda_channel_output_limit *pda = data;
u8 rawpower = 0;
rawpower = max(rawpower, pda->val_qpsk);
rawpower = max(rawpower, pda->val_bpsk);
rawpower = max(rawpower, pda->val_16qam);
rawpower = max(rawpower, pda->val_64qam); /* raw values are in 1/4 dBm units */ return rawpower / 4;
}
default: return 20;
}
}
staticint p54_generate_channel_lists(struct ieee80211_hw *dev)
{ struct p54_common *priv = dev->priv; struct p54_channel_list *list; unsignedint i, j, k, max_channel_num; int ret = 0;
u16 freq;
if ((priv->iq_autocal_len != priv->curve_data->entries) ||
(priv->iq_autocal_len != priv->output_limit->entries))
wiphy_err(dev->wiphy, "Unsupported or damaged EEPROM detected. " "You may not be able to use all channels.\n");
list = kzalloc(sizeof(*list), GFP_KERNEL); if (!list) {
ret = -ENOMEM; goto free;
}
priv->chan_num = max_channel_num;
priv->survey = kcalloc(max_channel_num, sizeof(struct survey_info),
GFP_KERNEL); if (!priv->survey) {
ret = -ENOMEM; goto free;
}
list->max_entries = max_channel_num;
list->channels = kcalloc(max_channel_num, sizeof(struct p54_channel_entry),
GFP_KERNEL); if (!list->channels) {
ret = -ENOMEM; goto free;
}
for (i = 0; i < max_channel_num; i++) { if (i < priv->iq_autocal_len) {
freq = le16_to_cpu(priv->iq_autocal[i].freq);
p54_update_channel_param(list, freq, CHAN_HAS_CAL);
}
if (i < priv->output_limit->entries) { struct p54_channel_entry *tmp;
/* sort the channel list by frequency */
sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
p54_compare_channels, NULL);
k = 0; for (i = 0, j = 0; i < NUM_NL80211_BANDS; i++) { if (p54_generate_band(dev, list, &k, i) == 0)
j++;
} if (j == 0) { /* no useable band available. */
ret = -EINVAL;
}
free: if (list) {
kfree(list->channels);
kfree(list);
} if (ret) {
kfree(priv->survey);
priv->survey = NULL;
}
wiphy_err(dev->wiphy, "please report this issue.\n"); return -EINVAL;
}
struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
{ struct p54_rssi_db_entry *entry; int i, found = -1;
if (!priv->rssi_db) return &p54_rssi_default;
entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset); for (i = 0; i < priv->rssi_db->entries; i++) { if (!same_band(freq, entry[i].freq)) continue;
if (found == -1) {
found = i; continue;
}
/* nearest match */ if (abs(freq - entry[i].freq) <
abs(freq - entry[found].freq)) {
found = i; continue;
} else { break;
}
}
return found < 0 ? &p54_rssi_default : &entry[found];
}
/* verify that at least the entry length/code fits */ while ((u8 *)entry <= end - sizeof(*entry)) {
entry_len = le16_to_cpu(entry->len);
data_len = ((entry_len - 1) << 1);
/* abort if entry exceeds whole structure */ if ((u8 *)entry + sizeof(*entry) + data_len > end) break;
switch (le16_to_cpu(entry->code)) { case PDR_MAC_ADDRESS: if (data_len != ETH_ALEN) break;
SET_IEEE80211_PERM_ADDR(dev, entry->data); break; case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS: if (priv->output_limit) break;
err = p54_convert_output_limits(dev, entry->data,
data_len); if (err) goto err; break; case PDR_PRISM_PA_CAL_CURVE_DATA: { struct pda_pa_curve_data *curve_data =
(struct pda_pa_curve_data *)entry->data; if (data_len < sizeof(*curve_data)) {
err = -EINVAL; goto err;
}
switch (curve_data->cal_method_rev) { case 0:
err = p54_convert_rev0(dev, curve_data); break; case 1:
err = p54_convert_rev1(dev, curve_data); break; default:
wiphy_err(dev->wiphy, "unknown curve data revision %d\n",
curve_data->cal_method_rev);
err = -ENODEV; break;
} if (err) goto err;
} break; case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
priv->iq_autocal = kmemdup(entry->data, data_len,
GFP_KERNEL); if (!priv->iq_autocal) {
err = -ENOMEM; goto err;
}
priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); break; case PDR_DEFAULT_COUNTRY:
p54_parse_default_country(dev, entry->data, data_len); break; case PDR_INTERFACE_LIST:
tmp = entry->data; while ((u8 *)tmp < entry->data + data_len) { struct exp_if *exp_if = tmp; if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000))
synth = le16_to_cpu(exp_if->variant);
tmp += sizeof(*exp_if);
} break; case PDR_HARDWARE_PLATFORM_COMPONENT_ID: if (data_len < 2) break;
priv->version = *(u8 *)(entry->data + 1); break; case PDR_RSSI_LINEAR_APPROXIMATION: case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
err = p54_parse_rssical(dev, entry->data, data_len,
le16_to_cpu(entry->code)); if (err) goto err; break; case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: { struct pda_custom_wrapper *pda = (void *) entry->data;
__le16 *src;
u16 *dst; int i;
if (priv->rssi_db || data_len < sizeof(*pda)) break;
priv->rssi_db = p54_convert_db(pda, data_len); if (!priv->rssi_db) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.