2 * Copyright 2008 Pavel Machek <pavel@suse.cz>
4 * Distribute under GPLv2.
6 * The original driver was written by:
7 * Jeff Lee <YY_Lee@issc.com.tw>
9 * and was adapted to the 2.6 kernel by:
10 * Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>
12 #include <net/mac80211.h>
13 #include <linux/usb.h>
17 #include "mlmetxrx_f.h"
20 #include "wblinux_f.h"
22 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
23 MODULE_LICENSE("GPL");
24 MODULE_VERSION("0.1");
26 static struct usb_device_id wb35_table[] __devinitdata = {
27 { USB_DEVICE(0x0416, 0x0035) },
28 { USB_DEVICE(0x18E8, 0x6201) },
29 { USB_DEVICE(0x18E8, 0x6206) },
30 { USB_DEVICE(0x18E8, 0x6217) },
31 { USB_DEVICE(0x18E8, 0x6230) },
32 { USB_DEVICE(0x18E8, 0x6233) },
33 { USB_DEVICE(0x1131, 0x2035) },
37 MODULE_DEVICE_TABLE(usb, wb35_table);
39 static struct ieee80211_rate wbsoft_rates[] = {
40 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
43 static struct ieee80211_channel wbsoft_channels[] = {
44 { .center_freq = 2412 },
47 static struct ieee80211_supported_band wbsoft_band_2GHz = {
48 .channels = wbsoft_channels,
49 .n_channels = ARRAY_SIZE(wbsoft_channels),
50 .bitrates = wbsoft_rates,
51 .n_bitrates = ARRAY_SIZE(wbsoft_rates),
54 static int wbsoft_add_interface(struct ieee80211_hw *dev,
55 struct ieee80211_if_init_conf *conf)
57 printk("wbsoft_add interface called\n");
61 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
62 struct ieee80211_if_init_conf *conf)
64 printk("wbsoft_remove interface called\n");
67 static void wbsoft_stop(struct ieee80211_hw *hw)
69 printk(KERN_INFO "%s called\n", __func__);
72 static int wbsoft_get_stats(struct ieee80211_hw *hw,
73 struct ieee80211_low_level_stats *stats)
75 printk(KERN_INFO "%s called\n", __func__);
79 static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
80 struct ieee80211_tx_queue_stats *stats)
82 printk(KERN_INFO "%s called\n", __func__);
86 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
87 unsigned int changed_flags,
88 unsigned int *total_flags,
89 int mc_count, struct dev_mc_list *mclist)
91 unsigned int new_flags;
95 if (*total_flags & FIF_PROMISC_IN_BSS)
96 new_flags |= FIF_PROMISC_IN_BSS;
97 else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32))
98 new_flags |= FIF_ALLMULTI;
100 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
102 *total_flags = new_flags;
105 static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
107 struct wbsoft_priv *priv = dev->priv;
109 MLMESendFrame(priv, skb->data, skb->len, FRAME_TYPE_802_11_MANAGEMENT);
114 static int wbsoft_start(struct ieee80211_hw *dev)
116 struct wbsoft_priv *priv = dev->priv;
118 priv->enabled = true;
123 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
125 struct wbsoft_priv *priv = dev->priv;
126 struct ieee80211_conf *conf = &dev->conf;
129 printk("wbsoft_config called\n");
131 /* Should use channel_num, or something, as that is already pre-translated */
135 hal_set_current_channel(&priv->sHwData, ch);
136 hal_set_beacon_period(&priv->sHwData, conf->beacon_int);
137 hal_set_accept_broadcast(&priv->sHwData, 1);
138 hal_set_accept_promiscuous(&priv->sHwData, 1);
139 hal_set_accept_multicast(&priv->sHwData, 1);
140 hal_set_accept_beacon(&priv->sHwData, 1);
141 hal_set_radio_mode(&priv->sHwData, 0);
146 static int wbsoft_config_interface(struct ieee80211_hw *dev,
147 struct ieee80211_vif *vif,
148 struct ieee80211_if_conf *conf)
150 printk("wbsoft_config_interface called\n");
154 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
156 printk("wbsoft_get_tsf called\n");
160 static const struct ieee80211_ops wbsoft_ops = {
162 .start = wbsoft_start,
164 .add_interface = wbsoft_add_interface,
165 .remove_interface = wbsoft_remove_interface,
166 .config = wbsoft_config,
167 .config_interface = wbsoft_config_interface,
168 .configure_filter = wbsoft_configure_filter,
169 .get_stats = wbsoft_get_stats,
170 .get_tx_stats = wbsoft_get_tx_stats,
171 .get_tsf = wbsoft_get_tsf,
174 static u8 LED_GRAY[20] = {
175 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
178 static u8 LED_GRAY2[30] = {
179 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 15, 14, 13, 12, 11, 10, 9, 8
183 static void hal_led_control(unsigned long data)
185 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
186 struct hw_data *pHwData = &adapter->sHwData;
187 struct wb35_reg *reg = &pHwData->reg;
188 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
189 u32 TimeInterval = 500, ltmp, ltmp2;
192 if (pHwData->SurpriseRemove)
195 if (pHwData->LED_control) {
196 ltmp2 = pHwData->LED_control & 0xff;
197 if (ltmp2 == 5) // 5 is WPS mode
200 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
202 case 1: // [0.2 On][0.1 Off]...
203 pHwData->LED_Blinking %= 3;
204 ltmp = 0x1010; // Led 1 & 0 Green and Red
205 if (pHwData->LED_Blinking == 2) // Turn off
208 case 2: // [0.1 On][0.1 Off]...
209 pHwData->LED_Blinking %= 2;
210 ltmp = 0x0010; // Led 0 red color
211 if (pHwData->LED_Blinking) // Turn off
214 case 3: // [0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.5 Off]...
215 pHwData->LED_Blinking %= 15;
216 ltmp = 0x0010; // Led 0 red color
217 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) // Turn off 0.6 sec
220 case 4: // [300 On][ off ]
221 ltmp = 0x1000; // Led 1 Green color
222 if (pHwData->LED_Blinking >= 3000)
223 ltmp = 0; // led maybe on after 300sec * 32bit counter overlap.
226 pHwData->LED_Blinking++;
228 reg->U1BC_LEDConfigure = ltmp;
229 if (LEDSet != 7) // Only 111 mode has 2 LEDs on PCB.
231 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; // Copy LED result to each LED control register
232 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
234 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
236 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) // If radio off
238 if (reg->U1BC_LEDConfigure & 0x1010) {
239 reg->U1BC_LEDConfigure &= ~0x1010;
240 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
244 case 4: // [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
245 if (!pHwData->LED_LinkOn) // Blink only if not Link On
247 // Blinking if scanning is on progress
248 if (pHwData->LED_Scanning) {
249 if (pHwData->LED_Blinking == 0) {
250 reg->U1BC_LEDConfigure |= 0x10;
251 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On
252 pHwData->LED_Blinking = 1;
255 reg->U1BC_LEDConfigure &= ~0x10;
256 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
257 pHwData->LED_Blinking = 0;
262 if (reg->U1BC_LEDConfigure & 0x10) {
263 reg->U1BC_LEDConfigure &= ~0x10;
264 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
269 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
270 reg->U1BC_LEDConfigure |= 0x10;
271 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
276 case 6: // [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
277 if (!pHwData->LED_LinkOn) // Blink only if not Link On
279 // Blinking if scanning is on progress
280 if (pHwData->LED_Scanning) {
281 if (pHwData->LED_Blinking == 0) {
282 reg->U1BC_LEDConfigure &= ~0xf;
283 reg->U1BC_LEDConfigure |= 0x10;
284 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On
285 pHwData->LED_Blinking = 1;
288 reg->U1BC_LEDConfigure &= ~0x1f;
289 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
290 pHwData->LED_Blinking = 0;
294 // 20060901 Gray blinking if in disconnect state and not scanning
295 ltmp = reg->U1BC_LEDConfigure;
296 reg->U1BC_LEDConfigure &= ~0x1f;
297 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
298 reg->U1BC_LEDConfigure |= 0x10;
299 reg->U1BC_LEDConfigure |=
300 LED_GRAY2[(pHwData->LED_Blinking % 30)];
302 pHwData->LED_Blinking++;
303 if (reg->U1BC_LEDConfigure != ltmp)
304 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
309 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
310 reg->U1BC_LEDConfigure |= 0x10;
311 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
316 case 5: // [101] Only 1 Led be placed on PCB and use LED_1 for showing
317 if (!pHwData->LED_LinkOn) // Blink only if not Link On
319 // Blinking if scanning is on progress
320 if (pHwData->LED_Scanning) {
321 if (pHwData->LED_Blinking == 0) {
322 reg->U1BC_LEDConfigure |=
324 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
325 pHwData->LED_Blinking = 1;
328 reg->U1BC_LEDConfigure &=
330 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off
331 pHwData->LED_Blinking = 0;
336 if (reg->U1BC_LEDConfigure & 0x1000) {
337 reg->U1BC_LEDConfigure &=
339 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off
343 // Is transmitting/receiving ??
344 if ((adapter->RxByteCount !=
345 pHwData->RxByteCountLast)
346 || (adapter->TxByteCount !=
347 pHwData->TxByteCountLast)) {
348 if ((reg->U1BC_LEDConfigure & 0x3000) !=
350 reg->U1BC_LEDConfigure |=
352 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
355 pHwData->RxByteCountLast =
356 adapter->RxByteCount;
357 pHwData->TxByteCountLast =
358 adapter->TxByteCount;
361 // Turn On LED_1 and blinking if transmitting/receiving
362 if ((reg->U1BC_LEDConfigure & 0x3000) !=
364 reg->U1BC_LEDConfigure &=
366 reg->U1BC_LEDConfigure |=
368 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
374 default: // Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active
375 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
376 reg->U1BC_LEDConfigure |= 0x3000; // LED_1 is always on and event enable
377 Wb35Reg_Write(pHwData, 0x03bc,
378 reg->U1BC_LEDConfigure);
381 if (pHwData->LED_Blinking) {
383 reg->U1BC_LEDConfigure &= ~0x0f;
384 reg->U1BC_LEDConfigure |= 0x10;
385 reg->U1BC_LEDConfigure |=
386 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
387 Wb35Reg_Write(pHwData, 0x03bc,
388 reg->U1BC_LEDConfigure);
390 pHwData->LED_Blinking += 2;
391 if (pHwData->LED_Blinking < 40)
394 pHwData->LED_Blinking = 0; // Stop blinking
395 reg->U1BC_LEDConfigure &= ~0x0f;
396 Wb35Reg_Write(pHwData, 0x03bc,
397 reg->U1BC_LEDConfigure);
402 if (pHwData->LED_LinkOn) {
403 if (!(reg->U1BC_LEDConfigure & 0x10)) // Check the LED_0
405 //Try to turn ON LED_0 after gray blinking
406 reg->U1BC_LEDConfigure |= 0x10;
407 pHwData->LED_Blinking = 1; //Start blinking
411 if (reg->U1BC_LEDConfigure & 0x10) // Check the LED_0
413 reg->U1BC_LEDConfigure &= ~0x10;
414 Wb35Reg_Write(pHwData, 0x03bc,
415 reg->U1BC_LEDConfigure);
421 //20060828.1 Active send null packet to avoid AP disconnect
422 if (pHwData->LED_LinkOn) {
423 pHwData->NullPacketCount += TimeInterval;
424 if (pHwData->NullPacketCount >=
425 DEFAULT_NULL_PACKET_COUNT) {
426 pHwData->NullPacketCount = 0;
431 pHwData->time_count += TimeInterval;
432 Wb35Tx_CurrentTime(adapter, pHwData->time_count); // 20060928 add
433 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
434 add_timer(&pHwData->LEDTimer);
437 static int hal_init_hardware(struct ieee80211_hw *hw)
439 struct wbsoft_priv *priv = hw->priv;
440 struct hw_data *pHwData = &priv->sHwData;
443 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
444 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
446 if (!Wb35Reg_initial(pHwData))
447 goto error_reg_destroy;
449 if (!Wb35Tx_initial(pHwData))
450 goto error_tx_destroy;
452 if (!Wb35Rx_initial(pHwData))
453 goto error_rx_destroy;
455 init_timer(&pHwData->LEDTimer);
456 pHwData->LEDTimer.function = hal_led_control;
457 pHwData->LEDTimer.data = (unsigned long)priv;
458 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
459 add_timer(&pHwData->LEDTimer);
461 SoftwareSet = hal_software_set(pHwData);
464 // Try to make sure the EEPROM contain
466 if (SoftwareSet != 0x82)
471 Wb35Tx_EP2VM_start(priv);
476 Wb35Rx_destroy(pHwData);
478 Wb35Tx_destroy(pHwData);
480 Wb35Reg_destroy(pHwData);
482 pHwData->SurpriseRemove = 1;
486 static int wb35_hw_init(struct ieee80211_hw *hw)
488 struct wbsoft_priv *priv = hw->priv;
489 struct hw_data *pHwData = &priv->sHwData;
496 pHwData->phy_type = RF_DECIDE_BY_INF;
498 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
499 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
501 priv->sLocalPara.region_INF = REGION_AUTO;
502 priv->sLocalPara.TxRateMode = RATE_AUTO;
503 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
504 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
505 priv->sLocalPara.bPreambleMode = AUTO_MODE;
506 priv->sLocalPara.bWepKeyError = false;
507 priv->sLocalPara.bToSelfPacketReceived = false;
508 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
510 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
512 err = hal_init_hardware(hw);
516 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
517 if (EEPROM_region != REGION_AUTO)
518 priv->sLocalPara.region = EEPROM_region;
520 if (priv->sLocalPara.region_INF != REGION_AUTO)
521 priv->sLocalPara.region = priv->sLocalPara.region_INF;
523 priv->sLocalPara.region = REGION_USA; /* default setting */
526 // Get Software setting flag from hal
527 priv->sLocalPara.boAntennaDiversity = false;
528 if (hal_software_set(pHwData) & 0x00000001)
529 priv->sLocalPara.boAntennaDiversity = true;
534 * If no user-defined address in the registry, use the addresss
535 * "burned" on the NIC instead.
537 pMacAddr = priv->sLocalPara.ThisMacAddress;
538 pMacAddr2 = priv->sLocalPara.PermanentAddress;
540 /* Reading ethernet address from EEPROM */
541 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
542 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
543 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
545 /* Set the user define MAC address */
546 hal_set_ethernet_address(pHwData,
547 priv->sLocalPara.ThisMacAddress);
550 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
551 #ifdef _PE_STATE_DUMP_
552 printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo);
554 hal_get_hw_radio_off(pHwData);
556 /* Waiting for HAL setting OK */
557 while (!hal_idle(pHwData))
562 HwRadioOff = hal_get_hw_radio_off(pHwData);
563 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
565 hal_set_radio_mode(pHwData,
566 (unsigned char)(priv->sLocalPara.RadioOffStatus.
568 || priv->sLocalPara.RadioOffStatus.
571 /* Notify hal that the driver is ready now. */
572 hal_driver_init_OK(pHwData) = 1;
578 static int wb35_probe(struct usb_interface *intf,
579 const struct usb_device_id *id_table)
581 struct usb_device *udev = interface_to_usbdev(intf);
582 struct usb_endpoint_descriptor *endpoint;
583 struct usb_host_interface *interface;
584 struct ieee80211_hw *dev;
585 struct wbsoft_priv *priv;
586 struct wb_usb *pWbUsb;
592 /* Check the device if it already be opened */
593 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
595 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
596 0x0, 0x400, <mp, 4, HZ * 100);
602 /* Is already initialized? */
603 ltmp = cpu_to_le32(ltmp);
609 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
617 spin_lock_init(&priv->SpinLock);
619 pWbUsb = &priv->sHwData.WbUsb;
622 interface = intf->cur_altsetting;
623 endpoint = &interface->endpoint[0].desc;
625 if (endpoint[2].wMaxPacketSize == 512) {
626 printk("[w35und] Working on USB 2.0\n");
630 err = wb35_hw_init(dev);
634 SET_IEEE80211_DEV(dev, &udev->dev);
636 struct hw_data *pHwData = &priv->sHwData;
637 unsigned char dev_addr[MAX_ADDR_LEN];
638 hal_get_permanent_address(pHwData, dev_addr);
639 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
642 dev->extra_tx_headroom = 12; /* FIXME */
643 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
644 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
646 dev->channel_change_time = 1000;
647 dev->max_signal = 100;
650 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
652 err = ieee80211_register_hw(dev);
656 usb_set_intfdata(intf, dev);
661 ieee80211_free_hw(dev);
667 static void hal_halt(struct hw_data *pHwData)
669 del_timer_sync(&pHwData->LEDTimer);
670 /* XXX: Wait for Timer DPC exit. */
672 Wb35Rx_destroy(pHwData);
673 Wb35Tx_destroy(pHwData);
674 Wb35Reg_destroy(pHwData);
677 static void wb35_hw_halt(struct wbsoft_priv *adapter)
679 Mds_Destroy(adapter);
681 /* Turn off Rx and Tx hardware ability */
682 hal_stop(&adapter->sHwData);
683 #ifdef _PE_USB_INI_DUMP_
684 printk("[w35und] Hal_stop O.K.\n");
686 /* Waiting Irp completed */
689 hal_halt(&adapter->sHwData);
692 static void wb35_disconnect(struct usb_interface *intf)
694 struct ieee80211_hw *hw = usb_get_intfdata(intf);
695 struct wbsoft_priv *priv = hw->priv;
699 ieee80211_stop_queues(hw);
700 ieee80211_unregister_hw(hw);
701 ieee80211_free_hw(hw);
703 usb_set_intfdata(intf, NULL);
704 usb_put_dev(interface_to_usbdev(intf));
707 static struct usb_driver wb35_driver = {
709 .id_table = wb35_table,
711 .disconnect = wb35_disconnect,
714 static int __init wb35_init(void)
716 return usb_register(&wb35_driver);
719 static void __exit wb35_exit(void)
721 usb_deregister(&wb35_driver);
724 module_init(wb35_init);
725 module_exit(wb35_exit);