2 * Copyright 2008 Pavel Machek <pavel@suse.cz>
4 * Distribute under GPLv2.
6 #include <net/mac80211.h>
11 #include "mlmetxrx_f.h"
14 #include "wblinux_f.h"
16 MODULE_AUTHOR("Original by: Jeff Lee<YY_Lee@issc.com.tw> Adapted to 2.6.x by Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>");
17 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
18 MODULE_LICENSE("GPL");
19 MODULE_VERSION("0.1");
21 static struct usb_device_id wb35_table
[] __devinitdata
= {
22 {USB_DEVICE(0x0416, 0x0035)},
23 {USB_DEVICE(0x18E8, 0x6201)},
24 {USB_DEVICE(0x18E8, 0x6206)},
25 {USB_DEVICE(0x18E8, 0x6217)},
26 {USB_DEVICE(0x18E8, 0x6230)},
27 {USB_DEVICE(0x18E8, 0x6233)},
28 {USB_DEVICE(0x1131, 0x2035)},
32 MODULE_DEVICE_TABLE(usb
, wb35_table
);
34 static struct ieee80211_rate wbsoft_rates
[] = {
35 { .bitrate
= 10, .flags
= IEEE80211_RATE_SHORT_PREAMBLE
},
38 static struct ieee80211_channel wbsoft_channels
[] = {
39 { .center_freq
= 2412},
42 static struct ieee80211_supported_band wbsoft_band_2GHz
= {
43 .channels
= wbsoft_channels
,
44 .n_channels
= ARRAY_SIZE(wbsoft_channels
),
45 .bitrates
= wbsoft_rates
,
46 .n_bitrates
= ARRAY_SIZE(wbsoft_rates
),
49 static int wbsoft_add_interface(struct ieee80211_hw
*dev
,
50 struct ieee80211_if_init_conf
*conf
)
52 printk("wbsoft_add interface called\n");
56 static void wbsoft_remove_interface(struct ieee80211_hw
*dev
,
57 struct ieee80211_if_init_conf
*conf
)
59 printk("wbsoft_remove interface called\n");
62 static void wbsoft_stop(struct ieee80211_hw
*hw
)
64 printk(KERN_INFO
"%s called\n", __func__
);
67 static int wbsoft_get_stats(struct ieee80211_hw
*hw
,
68 struct ieee80211_low_level_stats
*stats
)
70 printk(KERN_INFO
"%s called\n", __func__
);
74 static int wbsoft_get_tx_stats(struct ieee80211_hw
*hw
,
75 struct ieee80211_tx_queue_stats
*stats
)
77 printk(KERN_INFO
"%s called\n", __func__
);
81 static void wbsoft_configure_filter(struct ieee80211_hw
*dev
,
82 unsigned int changed_flags
,
83 unsigned int *total_flags
,
84 int mc_count
, struct dev_mc_list
*mclist
)
86 unsigned int new_flags
;
90 if (*total_flags
& FIF_PROMISC_IN_BSS
)
91 new_flags
|= FIF_PROMISC_IN_BSS
;
92 else if ((*total_flags
& FIF_ALLMULTI
) || (mc_count
> 32))
93 new_flags
|= FIF_ALLMULTI
;
95 dev
->flags
&= ~IEEE80211_HW_RX_INCLUDES_FCS
;
97 *total_flags
= new_flags
;
100 static int wbsoft_tx(struct ieee80211_hw
*dev
, struct sk_buff
*skb
)
102 struct wbsoft_priv
*priv
= dev
->priv
;
104 MLMESendFrame(priv
, skb
->data
, skb
->len
, FRAME_TYPE_802_11_MANAGEMENT
);
110 static int wbsoft_start(struct ieee80211_hw
*dev
)
112 struct wbsoft_priv
*priv
= dev
->priv
;
114 priv
->enabled
= true;
119 static int wbsoft_config(struct ieee80211_hw
*dev
, u32 changed
)
121 struct wbsoft_priv
*priv
= dev
->priv
;
122 struct ieee80211_conf
*conf
= &dev
->conf
;
125 printk("wbsoft_config called\n");
128 ch
.ChanNo
= 1; /* Should use channel_num, or something, as that is already pre-translated */
131 hal_set_current_channel(&priv
->sHwData
, ch
);
132 hal_set_beacon_period(&priv
->sHwData
, conf
->beacon_int
);
133 // hal_set_cap_info(&priv->sHwData, ?? );
134 // hal_set_ssid(struct hw_data * pHwData, u8 * pssid, u8 ssid_len); ??
135 hal_set_accept_broadcast(&priv
->sHwData
, 1);
136 hal_set_accept_promiscuous(&priv
->sHwData
, 1);
137 hal_set_accept_multicast(&priv
->sHwData
, 1);
138 hal_set_accept_beacon(&priv
->sHwData
, 1);
139 hal_set_radio_mode(&priv
->sHwData
, 0);
140 //hal_set_antenna_number( struct hw_data * pHwData, u8 number )
141 //hal_set_rf_power(struct hw_data * pHwData, u8 PowerIndex)
144 // hal_start_bss(&priv->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE); ??
146 //void hal_set_rates(struct hw_data * pHwData, u8 * pbss_rates,
147 // u8 length, unsigned char basic_rate_set)
152 static int wbsoft_config_interface(struct ieee80211_hw
*dev
,
153 struct ieee80211_vif
*vif
,
154 struct ieee80211_if_conf
*conf
)
156 printk("wbsoft_config_interface called\n");
160 static u64
wbsoft_get_tsf(struct ieee80211_hw
*dev
)
162 printk("wbsoft_get_tsf called\n");
166 static const struct ieee80211_ops wbsoft_ops
= {
168 .start
= wbsoft_start
, /* Start can be pretty much empty as we do wb35_hw_init() during probe? */
170 .add_interface
= wbsoft_add_interface
,
171 .remove_interface
= wbsoft_remove_interface
,
172 .config
= wbsoft_config
,
173 .config_interface
= wbsoft_config_interface
,
174 .configure_filter
= wbsoft_configure_filter
,
175 .get_stats
= wbsoft_get_stats
,
176 .get_tx_stats
= wbsoft_get_tx_stats
,
177 .get_tsf
= wbsoft_get_tsf
,
178 // conf_tx: hal_set_cwmin()/hal_set_cwmax;
181 static unsigned char wb35_hw_init(struct ieee80211_hw
*hw
)
183 struct wbsoft_priv
*priv
= hw
->priv
;
184 struct hw_data
* pHwData
;
192 // Setting default value for Linux
194 priv
->sLocalPara
.region_INF
= REGION_AUTO
;
195 priv
->sLocalPara
.TxRateMode
= RATE_AUTO
;
196 priv
->sLocalPara
.bMacOperationMode
= MODE_802_11_BG
; // B/G mode
197 priv
->Mds
.TxRTSThreshold
= DEFAULT_RTSThreshold
;
198 priv
->Mds
.TxFragmentThreshold
= DEFAULT_FRAGMENT_THRESHOLD
;
199 hal_set_phy_type( &priv
->sHwData
, RF_WB_242_1
);
200 priv
->sLocalPara
.MTUsize
= MAX_ETHERNET_PACKET_SIZE
;
201 priv
->sLocalPara
.bPreambleMode
= AUTO_MODE
;
202 priv
->sLocalPara
.RadioOffStatus
.boSwRadioOff
= false;
203 pHwData
= &priv
->sHwData
;
204 hal_set_phy_type( pHwData
, RF_DECIDE_BY_INF
);
206 //added by ws for wep key error detection
207 priv
->sLocalPara
.bWepKeyError
= false;
208 priv
->sLocalPara
.bToSelfPacketReceived
= false;
209 priv
->sLocalPara
.WepKeyDetectTimerCount
= 2 * 100; /// 2 seconds
213 pHwData
= &priv
->sHwData
;
214 if (!hal_init_hardware(hw
))
217 EEPROM_region
= hal_get_region_from_EEPROM( pHwData
);
218 if (EEPROM_region
!= REGION_AUTO
)
219 priv
->sLocalPara
.region
= EEPROM_region
;
221 if (priv
->sLocalPara
.region_INF
!= REGION_AUTO
)
222 priv
->sLocalPara
.region
= priv
->sLocalPara
.region_INF
;
224 priv
->sLocalPara
.region
= REGION_USA
; //default setting
227 // Get Software setting flag from hal
228 priv
->sLocalPara
.boAntennaDiversity
= false;
229 if (hal_software_set(pHwData
) & 0x00000001)
230 priv
->sLocalPara
.boAntennaDiversity
= true;
241 //=======================================
242 // Initialize the SME, SCAN, MLME, ROAM
243 //=======================================
248 // If no user-defined address in the registry, use the addresss "burned" on the NIC instead.
249 pMacAddr
= priv
->sLocalPara
.ThisMacAddress
;
250 pMacAddr2
= priv
->sLocalPara
.PermanentAddress
;
251 hal_get_permanent_address( pHwData
, priv
->sLocalPara
.PermanentAddress
);// Reading ethernet address from EEPROM
252 if (memcmp(pMacAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) == 0)
253 memcpy(pMacAddr
, pMacAddr2
, MAC_ADDR_LENGTH
);
255 // Set the user define MAC address
256 hal_set_ethernet_address(pHwData
, priv
->sLocalPara
.ThisMacAddress
);
259 //get current antenna
260 priv
->sLocalPara
.bAntennaNo
= hal_get_antenna_number(pHwData
);
261 #ifdef _PE_STATE_DUMP_
262 printk("Driver init, antenna no = %d\n", psLOCAL
->bAntennaNo
);
264 hal_get_hw_radio_off( pHwData
);
266 // Waiting for HAL setting OK
267 while (!hal_idle(pHwData
))
272 HwRadioOff
= hal_get_hw_radio_off( pHwData
);
273 priv
->sLocalPara
.RadioOffStatus
.boHwRadioOff
= !!HwRadioOff
;
275 hal_set_radio_mode( pHwData
, (unsigned char)(priv
->sLocalPara
.RadioOffStatus
.boSwRadioOff
|| priv
->sLocalPara
.RadioOffStatus
.boHwRadioOff
) );
277 hal_driver_init_OK(pHwData
) = 1; // Notify hal that the driver is ready now.
278 //set a tx power for reference.....
279 // sme_set_tx_power_level(priv, 12); FIXME?
286 case 3: Mds_Destroy( priv
);
288 case 1: hal_halt( pHwData
, NULL
);
295 static int wb35_probe(struct usb_interface
*intf
, const struct usb_device_id
*id_table
)
297 struct wb_usb
*pWbUsb
;
298 struct usb_host_interface
*interface
;
299 struct usb_endpoint_descriptor
*endpoint
;
301 struct usb_device
*udev
= interface_to_usbdev(intf
);
302 struct wbsoft_priv
*priv
;
303 struct ieee80211_hw
*dev
;
308 // 20060630.2 Check the device if it already be opened
309 nr
= usb_control_msg(udev
, usb_rcvctrlpipe( udev
, 0 ),
310 0x01, USB_TYPE_VENDOR
|USB_RECIP_DEVICE
|USB_DIR_IN
,
311 0x0, 0x400, <mp
, 4, HZ
*100 );
317 ltmp
= cpu_to_le32(ltmp
);
318 if (ltmp
) { // Is already initialized?
323 dev
= ieee80211_alloc_hw(sizeof(*priv
), &wbsoft_ops
);
331 spin_lock_init(&priv
->SpinLock
);
333 pWbUsb
= &priv
->sHwData
.WbUsb
;
336 interface
= intf
->cur_altsetting
;
337 endpoint
= &interface
->endpoint
[0].desc
;
339 if (endpoint
[2].wMaxPacketSize
== 512) {
340 printk("[w35und] Working on USB 2.0\n");
344 if (!wb35_hw_init(dev
)) {
349 SET_IEEE80211_DEV(dev
, &udev
->dev
);
351 struct hw_data
* pHwData
= &priv
->sHwData
;
352 unsigned char dev_addr
[MAX_ADDR_LEN
];
353 hal_get_permanent_address(pHwData
, dev_addr
);
354 SET_IEEE80211_PERM_ADDR(dev
, dev_addr
);
357 dev
->extra_tx_headroom
= 12; /* FIXME */
358 dev
->flags
= IEEE80211_HW_SIGNAL_UNSPEC
;
359 dev
->wiphy
->interface_modes
= BIT(NL80211_IFTYPE_STATION
);
361 dev
->channel_change_time
= 1000;
362 dev
->max_signal
= 100;
365 dev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &wbsoft_band_2GHz
;
367 err
= ieee80211_register_hw(dev
);
371 usb_set_intfdata(intf
, dev
);
376 ieee80211_free_hw(dev
);
382 static void wb35_hw_halt(struct wbsoft_priv
*adapter
)
384 Mds_Destroy( adapter
);
386 // Turn off Rx and Tx hardware ability
387 hal_stop( &adapter
->sHwData
);
388 #ifdef _PE_USB_INI_DUMP_
389 printk("[w35und] Hal_stop O.K.\n");
391 msleep(100);// Waiting Irp completed
394 hal_halt(&adapter
->sHwData
, NULL
);
398 static void wb35_disconnect(struct usb_interface
*intf
)
400 struct ieee80211_hw
*hw
= usb_get_intfdata(intf
);
401 struct wbsoft_priv
*priv
= hw
->priv
;
405 ieee80211_stop_queues(hw
);
406 ieee80211_unregister_hw(hw
);
407 ieee80211_free_hw(hw
);
409 usb_set_intfdata(intf
, NULL
);
410 usb_put_dev(interface_to_usbdev(intf
));
413 static struct usb_driver wb35_driver
= {
415 .id_table
= wb35_table
,
417 .disconnect
= wb35_disconnect
,
420 static int __init
wb35_init(void)
422 return usb_register(&wb35_driver
);
425 static void __exit
wb35_exit(void)
427 usb_deregister(&wb35_driver
);
430 module_init(wb35_init
);
431 module_exit(wb35_exit
);