コード例 #1
0
int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain)
{
	struct ieee80211_geo geo;
	const struct channel_range *range;
	int i;
	u8 channel;

	dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)),
		"regdomain %#04x\n", regdomain);

	range = zd_channel_range(regdomain);
	if (range->start == 0) {
		dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)),
			"zd1211 regdomain %#04x not supported\n",
			regdomain);
		return -EINVAL;
	}

	memset(&geo, 0, sizeof(geo));

	for (i = 0, channel = range->start; channel < range->end; channel++) {
		struct ieee80211_channel *chan = &geo.bg[i++];
		chan->freq = channel_frequencies[channel - 1];
		chan->channel = channel;
	}

	geo.bg_channels = i;
	memcpy(geo.name, "XX ", 4);
	ieee80211_set_geo(ieee, &geo);
	return 0;
}
コード例 #2
0
ファイル: zd_mac.c プロジェクト: Tigrouzen/k1099
static void set_rx_filter_handler(struct work_struct *work)
{
	struct zd_mac *mac =
		container_of(work, struct zd_mac, set_rx_filter_work);
	int r;

	dev_dbg_f(zd_mac_dev(mac), "\n");
	r = set_rx_filter(mac);
	if (r)
		dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
}
コード例 #3
0
ファイル: zd_mac.c プロジェクト: maraz/linux-2.6
void zd_process_intr(struct work_struct *work)
{
	u16 int_status;
	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);

	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
	if (int_status & INT_CFG_NEXT_BCN) {
		if (net_ratelimit())
			dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
	} else
		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");

	zd_chip_enable_hwint(&mac->chip);
}
コード例 #4
0
int zd_mac_set_mac_address(struct net_device *netdev, void *p)
{
	int r;
	unsigned long flags;
	struct sockaddr *addr = p;
	struct zd_mac *mac = zd_netdev_mac(netdev);
	struct zd_chip *chip = &mac->chip;
	DECLARE_MAC_BUF(mac2);

	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

	dev_dbg_f(zd_mac_dev(mac),
		  "Setting MAC to %s\n", print_mac(mac2, addr->sa_data));

	r = zd_write_mac_addr(chip, addr->sa_data);
	if (r)
		return r;

	spin_lock_irqsave(&mac->lock, flags);
	memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
	spin_unlock_irqrestore(&mac->lock, flags);

	return 0;
}
コード例 #5
0
u8 zd_mac_get_channel(struct zd_mac *mac)
{
	u8 channel = zd_chip_get_channel(&mac->chip);

	dev_dbg_f(zd_mac_dev(mac), "channel %u\n", channel);
	return channel;
}
コード例 #6
0
int zd_mac_set_mode(struct zd_mac *mac, u32 mode)
{
	struct ieee80211_device *ieee;

	switch (mode) {
	case IW_MODE_AUTO:
	case IW_MODE_ADHOC:
	case IW_MODE_INFRA:
		mac->netdev->type = ARPHRD_ETHER;
		break;
	case IW_MODE_MONITOR:
		mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP;
		break;
	default:
		dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode);
		return -EINVAL;
	}

	ieee = zd_mac_to_ieee80211(mac);
	ZD_ASSERT(!irqs_disabled());
	spin_lock_irq(&ieee->lock);
	ieee->iw_mode = mode;
	spin_unlock_irq(&ieee->lock);

	if (netif_running(mac->netdev))
		return reset_mode(mac);

	return 0;
}
コード例 #7
0
static void housekeeping_disable(struct zd_mac *mac)
{
	dev_dbg_f(zd_mac_dev(mac), "\n");
	cancel_rearming_delayed_workqueue(zd_workqueue,
		&mac->housekeeping.link_led_work);
	zd_chip_control_leds(&mac->chip, LED_OFF);
}
コード例 #8
0
static void set_channel(struct net_device *netdev, u8 channel)
{
	struct zd_mac *mac = zd_netdev_mac(netdev);

	dev_dbg_f(zd_mac_dev(mac), "channel %d\n", channel);

	zd_chip_set_channel(&mac->chip, channel);
}
コード例 #9
0
ファイル: zd_mac.c プロジェクト: ivucica/linux
static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
{
	int r;
	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
	struct ieee80211_rx_stats stats;
	const struct rx_status *status;

	if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
	               IEEE80211_FCS_LEN + sizeof(struct rx_status))
	{
		dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
			 skb->len);
		goto free_skb;
	}

	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
	if (r) {
		/* Only packets with rx errors are included here. */
		goto free_skb;
	}

	__skb_pull(skb, ZD_PLCP_HEADER_SIZE);
	__skb_trim(skb, skb->len -
		        (IEEE80211_FCS_LEN + sizeof(struct rx_status)));

	update_qual_rssi(mac, skb->data, skb->len, stats.signal,
		         status->signal_strength);

	r = filter_rx(ieee, skb->data, skb->len, &stats);
	if (r <= 0) {
		if (r < 0)
			dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
		goto free_skb;
	}

	if (ieee->iw_mode == IW_MODE_MONITOR)
		fill_rt_header(skb_push(skb, sizeof(struct zd_rt_hdr)), mac,
			       &stats, status);

	r = ieee80211_rx(ieee, skb, &stats);
	if (r)
		return;
free_skb:
	/* We are always in a soft irq. */
	dev_kfree_skb(skb);
}
コード例 #10
0
int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
{
	int r;
	struct zd_chip *chip = &mac->chip;
	u8 addr[ETH_ALEN];
	u8 default_regdomain;

	r = zd_chip_enable_int(chip);
	if (r)
		goto out;
	r = zd_chip_init_hw(chip, device_type);
	if (r)
		goto disable_int;

	zd_get_e2p_mac_addr(chip, addr);
	r = zd_write_mac_addr(chip, addr);
	if (r)
		goto disable_int;
	ZD_ASSERT(!irqs_disabled());
	spin_lock_irq(&mac->lock);
	memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
	spin_unlock_irq(&mac->lock);

	r = zd_read_regdomain(chip, &default_regdomain);
	if (r)
		goto disable_int;
	if (!zd_regdomain_supported(default_regdomain)) {
		dev_dbg_f(zd_mac_dev(mac),
			  "Regulatory Domain %#04x is not supported.\n",
		          default_regdomain);
		r = -EINVAL;
		goto disable_int;
	}
	spin_lock_irq(&mac->lock);
	mac->regdomain = mac->default_regdomain = default_regdomain;
	spin_unlock_irq(&mac->lock);
	r = reset_channel(mac);
	if (r)
		goto disable_int;

	/* We must inform the device that we are doing encryption/decryption in
	 * software at the moment. */
	r = zd_set_encryption_type(chip, ENC_SNIFFER);
	if (r)
		goto disable_int;

	r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain);
	if (r)
		goto disable_int;

	r = 0;
disable_int:
	zd_chip_disable_int(chip);
out:
	return r;
}
コード例 #11
0
ファイル: zd_netdev.c プロジェクト: FatSunHYS/OSCourseDesign
static int iw_get_range(struct net_device *netdev,
	               struct iw_request_info *info,
		       union iwreq_data *req, char *extra)
{
	struct iw_range *range = (struct iw_range *)extra;

	dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
	req->data.length = sizeof(*range);
	return zd_mac_get_range(zd_netdev_mac(netdev), range);
}
コード例 #12
0
ファイル: zd_mac.c プロジェクト: Tigrouzen/k1099
static void zd_op_configure_filter(struct ieee80211_hw *hw,
			unsigned int changed_flags,
			unsigned int *new_flags,
			int mc_count, struct dev_mc_list *mclist)
{
	struct zd_mc_hash hash;
	struct zd_mac *mac = zd_hw_mac(hw);
	unsigned long flags;
	int i;

	/* Only deal with supported flags */
	changed_flags &= SUPPORTED_FIF_FLAGS;
	*new_flags &= SUPPORTED_FIF_FLAGS;

	/* changed_flags is always populated but this driver
	 * doesn't support all FIF flags so its possible we don't
	 * need to do anything */
	if (!changed_flags)
		return;

	if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
		zd_mc_add_all(&hash);
	} else {
		DECLARE_MAC_BUF(macbuf);

		zd_mc_clear(&hash);
		for (i = 0; i < mc_count; i++) {
			if (!mclist)
				break;
			dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
				  print_mac(macbuf, mclist->dmi_addr));
			zd_mc_add_addr(&hash, mclist->dmi_addr);
			mclist = mclist->next;
		}
	}

	spin_lock_irqsave(&mac->lock, flags);
	mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
	mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
	mac->multicast_hash = hash;
	spin_unlock_irqrestore(&mac->lock, flags);
	queue_work(zd_workqueue, &mac->set_multicast_hash_work);

	if (changed_flags & FIF_CONTROL)
		queue_work(zd_workqueue, &mac->set_rx_filter_work);

	/* no handling required for FIF_OTHER_BSS as we don't currently
	 * do BSSID filtering */
	/* FIXME: in future it would be nice to enable the probe response
	 * filter (so that the driver doesn't see them) until
	 * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd
	 * have to schedule work to enable prbresp reception, which might
	 * happen too late. For now we'll just listen and forward them all the
	 * time. */
}
コード例 #13
0
ファイル: zd_mac.c プロジェクト: ivucica/linux
int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
{
	struct sk_buff *skb;

	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
	if (!skb) {
		dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
		return -ENOMEM;
	}
	skb_reserve(skb, sizeof(struct zd_rt_hdr));
	memcpy(__skb_put(skb, length), buffer, length);
	skb_queue_tail(&mac->rx_queue, skb);
	tasklet_schedule(&mac->rx_tasklet);
	return 0;
}
コード例 #14
0
static void set_security(struct net_device *netdev,
			 struct ieee80211_security *sec)
{
	struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev);
	struct ieee80211_security *secinfo = &ieee->sec;
	int keyidx;

	dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");

	for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
		if (sec->flags & (1<<keyidx)) {
			secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
			secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
			memcpy(secinfo->keys[keyidx], sec->keys[keyidx],
			       SCM_KEY_LEN);
		}

	if (sec->flags & SEC_ACTIVE_KEY) {
		secinfo->active_key = sec->active_key;
		dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
			"   .active_key = %d\n", sec->active_key);
	}
	if (sec->flags & SEC_UNICAST_GROUP) {
		secinfo->unicast_uses_group = sec->unicast_uses_group;
		dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
			"   .unicast_uses_group = %d\n",
			sec->unicast_uses_group);
	}
	if (sec->flags & SEC_LEVEL) {
		secinfo->level = sec->level;
		dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
			"   .level = %d\n", sec->level);
	}
	if (sec->flags & SEC_ENABLED) {
		secinfo->enabled = sec->enabled;
		dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
			"   .enabled = %d\n", sec->enabled);
	}
	if (sec->flags & SEC_ENCRYPT) {
		secinfo->encrypt = sec->encrypt;
		dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
			"   .encrypt = %d\n", sec->encrypt);
	}
	if (sec->flags & SEC_AUTH_MODE) {
		secinfo->auth_mode = sec->auth_mode;
		dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
			"   .auth_mode = %d\n", sec->auth_mode);
	}
}
コード例 #15
0
ファイル: zd_mac.c プロジェクト: Tigrouzen/k1099
static void link_led_handler(struct work_struct *work)
{
	struct zd_mac *mac =
		container_of(work, struct zd_mac, housekeeping.link_led_work.work);
	struct zd_chip *chip = &mac->chip;
	int is_associated;
	int r;

	spin_lock_irq(&mac->lock);
	is_associated = mac->associated;
	spin_unlock_irq(&mac->lock);

	r = zd_chip_control_leds(chip,
		                 is_associated ? LED_ASSOCIATED : LED_SCANNING);
	if (r)
		dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);

	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
		           LINK_LED_WORK_DELAY);
}
コード例 #16
0
ファイル: zd_netdev.c プロジェクト: FatSunHYS/OSCourseDesign
static int iw_get_freq(struct net_device *netdev,
	           struct iw_request_info *info,
		   union iwreq_data *req, char *extra)
{
	int r;
	struct zd_mac *mac = zd_netdev_mac(netdev);
	struct iw_freq *freq = &req->freq;
	u8 channel;
	u8 flags;

	r = zd_mac_get_channel(mac, &channel, &flags);
	if (r)
		return r;

	freq->flags = (flags & MAC_FIXED_CHANNEL) ?
		      IW_FREQ_FIXED : IW_FREQ_AUTO;
	dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
		  (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
	return zd_channel_to_freq(freq, channel);
}
コード例 #17
0
ファイル: zd_mac.c プロジェクト: Tigrouzen/k1099
static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   struct ieee80211_bss_conf *bss_conf,
				   u32 changes)
{
	struct zd_mac *mac = zd_hw_mac(hw);
	unsigned long flags;

	dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);

	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
		spin_lock_irqsave(&mac->lock, flags);
		mac->short_preamble = bss_conf->use_short_preamble;
		if (!mac->updating_rts_rate) {
			mac->updating_rts_rate = 1;
			/* FIXME: should disable TX here, until work has
			 * completed and RTS_CTS reg is updated */
			queue_work(zd_workqueue, &mac->set_rts_cts_work);
		}
		spin_unlock_irqrestore(&mac->lock, flags);
	}
}
コード例 #18
0
ファイル: zd_mac.c プロジェクト: ivucica/linux
void zd_mac_set_multicast_list(struct net_device *dev)
{
	struct zd_mc_hash hash;
	struct zd_mac *mac = zd_netdev_mac(dev);
	struct dev_mc_list *mc;
	unsigned long flags;

	if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
		zd_mc_add_all(&hash);
	} else {
		zd_mc_clear(&hash);
		for (mc = dev->mc_list; mc; mc = mc->next) {
			dev_dbg_f(zd_mac_dev(mac), "mc addr " MAC_FMT "\n",
				  MAC_ARG(mc->dmi_addr));
			zd_mc_add_addr(&hash, mc->dmi_addr);
		}
	}

	spin_lock_irqsave(&mac->lock, flags);
	mac->multicast_hash = hash;
	spin_unlock_irqrestore(&mac->lock, flags);
	queue_work(zd_workqueue, &mac->set_multicast_hash_work);
}
コード例 #19
0
static void bssinfo_change(struct net_device *netdev, u32 changes)
{
	struct zd_mac *mac = zd_netdev_mac(netdev);
	struct ieee80211softmac_device *softmac = ieee80211_priv(netdev);
	struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo;
	int need_set_rts_cts = 0;
	int need_set_rates = 0;
	u16 basic_rates;
	unsigned long flags;

	dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);

	if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) {
		spin_lock_irqsave(&mac->lock, flags);
		mac->short_preamble = bssinfo->short_preamble;
		spin_unlock_irqrestore(&mac->lock, flags);
		need_set_rts_cts = 1;
	}

	if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) {
		/* Set RTS rate to highest available basic rate */
		u8 hi_rate = ieee80211softmac_highest_supported_rate(softmac,
			&bssinfo->supported_rates, 1);
		hi_rate = rate_to_zd_rate(hi_rate);

		spin_lock_irqsave(&mac->lock, flags);
		if (hi_rate != mac->rts_rate) {
			mac->rts_rate = hi_rate;
			need_set_rts_cts = 1;
		}
		spin_unlock_irqrestore(&mac->lock, flags);

		/* Set basic rates */
		need_set_rates = 1;
		if (bssinfo->supported_rates.count == 0) {
			/* Allow the device to be flexible */
			basic_rates = CR_RATES_80211B | CR_RATES_80211G;
		} else {
			int i = 0;
			basic_rates = 0;

			for (i = 0; i < bssinfo->supported_rates.count; i++) {
				u16 rate = bssinfo->supported_rates.rates[i];
				if ((rate & IEEE80211_BASIC_RATE_MASK) == 0)
					continue;

				rate &= ~IEEE80211_BASIC_RATE_MASK;
				basic_rates |= rate_to_cr_rate(rate);
			}
		}
		spin_lock_irqsave(&mac->lock, flags);
		mac->basic_rates = basic_rates;
		spin_unlock_irqrestore(&mac->lock, flags);
	}

	/* Schedule any changes we made above */

	spin_lock_irqsave(&mac->lock, flags);
	if (need_set_rts_cts && !mac->updating_rts_rate) {
		mac->updating_rts_rate = 1;
		netif_stop_queue(mac->netdev);
		queue_delayed_work(zd_workqueue, &mac->set_rts_cts_work, 0);
	}
	if (need_set_rates && !mac->updating_basic_rates) {
		mac->updating_basic_rates = 1;
		netif_stop_queue(mac->netdev);
		queue_delayed_work(zd_workqueue, &mac->set_basic_rates_work,
				   0);
	}
	spin_unlock_irqrestore(&mac->lock, flags);
}
コード例 #20
0
static void housekeeping_enable(struct zd_mac *mac)
{
	dev_dbg_f(zd_mac_dev(mac), "\n");
	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
			   0);
}