]>
Commit | Line | Data |
---|---|---|
c2478d39 LF |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
c2478d39 | 14 | ******************************************************************************/ |
c2478d39 | 15 | |
9aa39bc4 | 16 | #define pr_fmt(fmt) "R8188EU: " fmt |
c2478d39 LF |
17 | #include <osdep_service.h> |
18 | #include <drv_types.h> | |
19 | #include <recv_osdep.h> | |
20 | #include <xmit_osdep.h> | |
21 | #include <hal_intf.h> | |
c2478d39 | 22 | #include <linux/usb.h> |
d249db9e | 23 | #include <linux/vmalloc.h> |
0a0796eb | 24 | #include <mon.h> |
c2478d39 LF |
25 | #include <osdep_intf.h> |
26 | ||
17452ee9 | 27 | #include <usb_ops_linux.h> |
c2478d39 LF |
28 | #include <rtw_ioctl.h> |
29 | ||
6955832f IS |
30 | #include "rtl8188e_hal.h" |
31 | ||
c2478d39 LF |
32 | #define USB_VENDER_ID_REALTEK 0x0bda |
33 | ||
34 | /* DID_USB_v916_20130116 */ | |
35 | static struct usb_device_id rtw_usb_id_tbl[] = { | |
36 | /*=== Realtek demoboard ===*/ | |
37 | {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */ | |
38 | {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */ | |
39 | /*=== Customer ID ===*/ | |
40 | /****** 8188EUS ********/ | |
a2fa6721 | 41 | {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ |
08951f10 | 42 | {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ |
df3f4edc | 43 | {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ |
260ea9c2 | 44 | {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ |
6d4556fc | 45 | {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ |
5a1d4c5d | 46 | {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ |
8626d524 | 47 | {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ |
c2478d39 LF |
48 | {} /* Terminating entry */ |
49 | }; | |
50 | ||
51 | MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl); | |
52 | ||
c2478d39 LF |
53 | static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) |
54 | { | |
55 | int i; | |
c2478d39 LF |
56 | struct dvobj_priv *pdvobjpriv; |
57 | struct usb_host_config *phost_conf; | |
58 | struct usb_config_descriptor *pconf_desc; | |
59 | struct usb_host_interface *phost_iface; | |
60 | struct usb_interface_descriptor *piface_desc; | |
c2478d39 LF |
61 | struct usb_endpoint_descriptor *pendp_desc; |
62 | struct usb_device *pusbd; | |
63 | ||
fadbe0cd | 64 | pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); |
574502ca | 65 | if (!pdvobjpriv) |
586b0632 | 66 | return NULL; |
c2478d39 LF |
67 | |
68 | pdvobjpriv->pusbintf = usb_intf; | |
69 | pusbd = interface_to_usbdev(usb_intf); | |
70 | pdvobjpriv->pusbdev = pusbd; | |
71 | usb_set_intfdata(usb_intf, pdvobjpriv); | |
72 | ||
73 | pdvobjpriv->RtNumInPipes = 0; | |
74 | pdvobjpriv->RtNumOutPipes = 0; | |
75 | ||
76 | phost_conf = pusbd->actconfig; | |
77 | pconf_desc = &phost_conf->desc; | |
78 | ||
79 | phost_iface = &usb_intf->altsetting[0]; | |
80 | piface_desc = &phost_iface->desc; | |
81 | ||
82 | pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; | |
83 | pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; | |
c2478d39 | 84 | |
c6724919 | 85 | for (i = 0; i < piface_desc->bNumEndpoints; i++) { |
73fbfbfe | 86 | int ep_num; |
37ad17a4 | 87 | |
6179ed59 JS |
88 | pendp_desc = &phost_iface->endpoint[i].desc; |
89 | ||
90 | ep_num = usb_endpoint_num(pendp_desc); | |
91 | ||
92 | if (usb_endpoint_is_bulk_in(pendp_desc)) { | |
93 | pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num; | |
94 | pdvobjpriv->RtNumInPipes++; | |
95 | } else if (usb_endpoint_is_int_in(pendp_desc)) { | |
96 | pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num; | |
97 | pdvobjpriv->RtNumInPipes++; | |
98 | } else if (usb_endpoint_is_bulk_out(pendp_desc)) { | |
99 | pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = | |
100 | ep_num; | |
101 | pdvobjpriv->RtNumOutPipes++; | |
c2478d39 LF |
102 | } |
103 | } | |
104 | ||
21335144 | 105 | if (pusbd->speed == USB_SPEED_HIGH) |
c2478d39 | 106 | pdvobjpriv->ishighspeed = true; |
21335144 | 107 | else |
c2478d39 | 108 | pdvobjpriv->ishighspeed = false; |
c2478d39 | 109 | |
418f9642 | 110 | mutex_init(&pdvobjpriv->usb_vendor_req_mutex); |
705a3136 | 111 | usb_get_dev(pusbd); |
586b0632 | 112 | |
c2478d39 LF |
113 | return pdvobjpriv; |
114 | } | |
115 | ||
116 | static void usb_dvobj_deinit(struct usb_interface *usb_intf) | |
117 | { | |
118 | struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf); | |
119 | ||
c2478d39 LF |
120 | usb_set_intfdata(usb_intf, NULL); |
121 | if (dvobj) { | |
122 | /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */ | |
123 | if ((dvobj->NumInterfaces != 2 && | |
124 | dvobj->NumInterfaces != 3) || | |
125 | (dvobj->InterfaceNumber == 1)) { | |
126 | if (interface_to_usbdev(usb_intf)->state != | |
127 | USB_STATE_NOTATTACHED) { | |
128 | /* If we didn't unplug usb dongle and | |
129 | * remove/insert module, driver fails | |
130 | * on sitesurvey for the first time when | |
131 | * device is up . Reset usb port for sitesurvey | |
132 | * fail issue. */ | |
9aa39bc4 | 133 | pr_debug("usb attached..., try to reset usb device\n"); |
c2478d39 LF |
134 | usb_reset_device(interface_to_usbdev(usb_intf)); |
135 | } | |
136 | } | |
f0e7a514 | 137 | |
f0e7a514 | 138 | mutex_destroy(&dvobj->usb_vendor_req_mutex); |
c2478d39 LF |
139 | kfree(dvobj); |
140 | } | |
141 | ||
142 | usb_put_dev(interface_to_usbdev(usb_intf)); | |
143 | ||
c2478d39 LF |
144 | } |
145 | ||
fd5d86d2 | 146 | void usb_intf_stop(struct adapter *padapter) |
c2478d39 LF |
147 | { |
148 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n")); | |
149 | ||
8895f04b | 150 | /* disable_hw_interrupt */ |
c2478d39 LF |
151 | if (!padapter->bSurpriseRemoved) { |
152 | /* device still exists, so driver can do i/o operation */ | |
153 | /* TODO: */ | |
154 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, | |
155 | ("SurpriseRemoved == false\n")); | |
156 | } | |
157 | ||
158 | /* cancel in irp */ | |
159 | rtw_hal_inirp_deinit(padapter); | |
160 | ||
161 | /* cancel out irp */ | |
14af3550 | 162 | usb_write_port_cancel(padapter); |
c2478d39 LF |
163 | |
164 | /* todo:cancel other irps */ | |
165 | ||
166 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n")); | |
167 | } | |
168 | ||
169 | static void rtw_dev_unload(struct adapter *padapter) | |
170 | { | |
171 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n")); | |
172 | ||
173 | if (padapter->bup) { | |
9aa39bc4 | 174 | pr_debug("===> rtw_dev_unload\n"); |
c2478d39 LF |
175 | padapter->bDriverStopped = true; |
176 | if (padapter->xmitpriv.ack_tx) | |
177 | rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP); | |
178 | /* s3. */ | |
fd5d86d2 | 179 | usb_intf_stop(padapter); |
c2478d39 LF |
180 | /* s4. */ |
181 | if (!padapter->pwrctrlpriv.bInternalAutoSuspend) | |
182 | rtw_stop_drv_threads(padapter); | |
183 | ||
184 | /* s5. */ | |
185 | if (!padapter->bSurpriseRemoved) { | |
186 | rtw_hal_deinit(padapter); | |
187 | padapter->bSurpriseRemoved = true; | |
188 | } | |
189 | ||
190 | padapter->bup = false; | |
191 | } else { | |
192 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, | |
193 | ("r871x_dev_unload():padapter->bup == false\n")); | |
194 | } | |
195 | ||
9aa39bc4 | 196 | pr_debug("<=== rtw_dev_unload\n"); |
c2478d39 LF |
197 | |
198 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n")); | |
199 | } | |
200 | ||
c2478d39 LF |
201 | static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) |
202 | { | |
203 | struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); | |
204 | struct adapter *padapter = dvobj->if1; | |
205 | struct net_device *pnetdev = padapter->pnetdev; | |
206 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
207 | struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; | |
ed737494 | 208 | unsigned long start_time = jiffies; |
c2478d39 | 209 | |
9aa39bc4 | 210 | pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid); |
c2478d39 LF |
211 | |
212 | if ((!padapter->bup) || (padapter->bDriverStopped) || | |
213 | (padapter->bSurpriseRemoved)) { | |
9aa39bc4 | 214 | pr_debug("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", |
c2478d39 LF |
215 | padapter->bup, padapter->bDriverStopped, |
216 | padapter->bSurpriseRemoved); | |
217 | goto exit; | |
218 | } | |
219 | ||
220 | pwrpriv->bInSuspend = true; | |
221 | rtw_cancel_all_timer(padapter); | |
222 | LeaveAllPowerSaveMode(padapter); | |
223 | ||
f18c566e | 224 | mutex_lock(&pwrpriv->mutex_lock); |
c2478d39 LF |
225 | /* s1. */ |
226 | if (pnetdev) { | |
227 | netif_carrier_off(pnetdev); | |
945c0972 | 228 | netif_tx_stop_all_queues(pnetdev); |
c2478d39 LF |
229 | } |
230 | ||
231 | /* s2. */ | |
232 | rtw_disassoc_cmd(padapter, 0, false); | |
233 | ||
234 | if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && | |
235 | check_fwstate(pmlmepriv, _FW_LINKED)) { | |
9aa39bc4 | 236 | pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n", |
c2478d39 LF |
237 | __func__, __LINE__, |
238 | pmlmepriv->cur_network.network.Ssid.Ssid, | |
239 | pmlmepriv->cur_network.network.MacAddress, | |
240 | pmlmepriv->cur_network.network.Ssid.SsidLength, | |
241 | pmlmepriv->assoc_ssid.SsidLength); | |
242 | ||
243 | pmlmepriv->to_roaming = 1; | |
244 | } | |
245 | /* s2-2. indicate disconnect to os */ | |
246 | rtw_indicate_disconnect(padapter); | |
247 | /* s2-3. */ | |
b4ba3b57 | 248 | rtw_free_assoc_resources(padapter); |
c2478d39 LF |
249 | /* s2-4. */ |
250 | rtw_free_network_queue(padapter, true); | |
251 | ||
252 | rtw_dev_unload(padapter); | |
f18c566e | 253 | mutex_unlock(&pwrpriv->mutex_lock); |
c2478d39 LF |
254 | |
255 | if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) | |
256 | rtw_indicate_scan_done(padapter, 1); | |
257 | ||
258 | if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) | |
259 | rtw_indicate_disconnect(padapter); | |
260 | ||
261 | exit: | |
7d708e52 | 262 | pr_debug("<=== %s .............. in %dms\n", __func__, |
ed737494 | 263 | jiffies_to_msecs(jiffies - start_time)); |
c2478d39 | 264 | |
7d708e52 | 265 | return 0; |
c2478d39 LF |
266 | } |
267 | ||
0aba3f41 | 268 | static int rtw_resume_process(struct adapter *padapter) |
c2478d39 LF |
269 | { |
270 | struct net_device *pnetdev; | |
271 | struct pwrctrl_priv *pwrpriv = NULL; | |
272 | int ret = -1; | |
ed737494 | 273 | unsigned long start_time = jiffies; |
c2478d39 | 274 | |
9aa39bc4 | 275 | pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid); |
c2478d39 LF |
276 | |
277 | if (padapter) { | |
278 | pnetdev = padapter->pnetdev; | |
279 | pwrpriv = &padapter->pwrctrlpriv; | |
280 | } else { | |
281 | goto exit; | |
282 | } | |
283 | ||
f18c566e | 284 | mutex_lock(&pwrpriv->mutex_lock); |
c2478d39 | 285 | rtw_reset_drv_sw(padapter); |
89b90c68 | 286 | pwrpriv->bkeepfwalive = false; |
c2478d39 | 287 | |
9aa39bc4 | 288 | pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); |
b091c6b6 | 289 | if (netdev_open(pnetdev) != 0) { |
23bf4042 | 290 | mutex_unlock(&pwrpriv->mutex_lock); |
c2478d39 | 291 | goto exit; |
23bf4042 | 292 | } |
c2478d39 LF |
293 | |
294 | netif_device_attach(pnetdev); | |
295 | netif_carrier_on(pnetdev); | |
296 | ||
f18c566e | 297 | mutex_unlock(&pwrpriv->mutex_lock); |
c2478d39 | 298 | |
c2478d39 LF |
299 | rtw_roaming(padapter, NULL); |
300 | ||
301 | ret = 0; | |
302 | exit: | |
23bf4042 | 303 | if (pwrpriv) |
c2478d39 | 304 | pwrpriv->bInSuspend = false; |
9aa39bc4 | 305 | pr_debug("<=== %s return %d.............. in %dms\n", __func__, |
ed737494 | 306 | ret, jiffies_to_msecs(jiffies - start_time)); |
c2478d39 | 307 | |
c2478d39 LF |
308 | return ret; |
309 | } | |
310 | ||
0aba3f41 | 311 | static int rtw_resume(struct usb_interface *pusb_intf) |
312 | { | |
313 | struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); | |
314 | struct adapter *padapter = dvobj->if1; | |
315 | ||
316 | return rtw_resume_process(padapter); | |
317 | } | |
318 | ||
c2478d39 LF |
319 | /* |
320 | * drv_init() - a device potentially for us | |
321 | * | |
322 | * notes: drv_init() is called when the bus driver has located | |
323 | * a card for us to support. | |
324 | * We accept the new device by returning 0. | |
325 | */ | |
326 | ||
327 | static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, | |
328 | struct usb_interface *pusb_intf, const struct usb_device_id *pdid) | |
329 | { | |
330 | struct adapter *padapter = NULL; | |
331 | struct net_device *pnetdev = NULL; | |
0a0796eb | 332 | struct net_device *pmondev; |
c2478d39 LF |
333 | int status = _FAIL; |
334 | ||
2397c6e0 | 335 | padapter = (struct adapter *)vzalloc(sizeof(*padapter)); |
c2478d39 LF |
336 | if (padapter == NULL) |
337 | goto exit; | |
338 | padapter->dvobj = dvobj; | |
339 | dvobj->if1 = padapter; | |
340 | ||
341 | padapter->bDriverStopped = true; | |
fc8b5ae9 | 342 | mutex_init(&padapter->hw_init_mutex); |
c2478d39 | 343 | |
c2478d39 LF |
344 | pnetdev = rtw_init_netdev(padapter); |
345 | if (pnetdev == NULL) | |
0f56c6e9 | 346 | goto free_adapter; |
c2478d39 LF |
347 | SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj)); |
348 | padapter = rtw_netdev_priv(pnetdev); | |
349 | ||
0a0796eb JS |
350 | if (padapter->registrypriv.monitor_enable) { |
351 | pmondev = rtl88eu_mon_init(); | |
352 | if (pmondev == NULL) | |
353 | netdev_warn(pnetdev, "Failed to initialize monitor interface"); | |
354 | padapter->pmondev = pmondev; | |
355 | } | |
356 | ||
6955832f IS |
357 | padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); |
358 | if (!padapter->HalData) | |
359 | DBG_88E("cant not alloc memory for HAL DATA\n"); | |
c2478d39 | 360 | |
c2478d39 LF |
361 | /* step read_chip_version */ |
362 | rtw_hal_read_chip_version(padapter); | |
363 | ||
364 | /* step usb endpoint mapping */ | |
365 | rtw_hal_chip_configure(padapter); | |
366 | ||
367 | /* step read efuse/eeprom data and get mac_addr */ | |
368 | rtw_hal_read_chip_info(padapter); | |
369 | ||
370 | /* step 5. */ | |
371 | if (rtw_init_drv_sw(padapter) == _FAIL) { | |
372 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, | |
373 | ("Initialize driver software resource Failed!\n")); | |
374 | goto free_hal_data; | |
375 | } | |
376 | ||
377 | #ifdef CONFIG_PM | |
378 | if (padapter->pwrctrlpriv.bSupportRemoteWakeup) { | |
379 | dvobj->pusbdev->do_remote_wakeup = 1; | |
380 | pusb_intf->needs_remote_wakeup = 1; | |
381 | device_init_wakeup(&pusb_intf->dev, 1); | |
9aa39bc4 SM |
382 | pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n"); |
383 | pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n", | |
c2478d39 LF |
384 | device_may_wakeup(&pusb_intf->dev)); |
385 | } | |
386 | #endif | |
387 | ||
388 | /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto | |
389 | * suspend influence */ | |
390 | if (usb_autopm_get_interface(pusb_intf) < 0) | |
9aa39bc4 | 391 | pr_debug("can't get autopm:\n"); |
c2478d39 LF |
392 | |
393 | /* alloc dev name after read efuse. */ | |
394 | rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname); | |
395 | rtw_macaddr_cfg(padapter->eeprompriv.mac_addr); | |
c2478d39 | 396 | memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN); |
9aa39bc4 | 397 | pr_debug("MAC Address from pnetdev->dev_addr = %pM\n", |
c2478d39 LF |
398 | pnetdev->dev_addr); |
399 | ||
400 | /* step 6. Tell the network stack we exist */ | |
401 | if (register_netdev(pnetdev) != 0) { | |
402 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n")); | |
403 | goto free_hal_data; | |
404 | } | |
405 | ||
9aa39bc4 | 406 | pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n" |
c2478d39 LF |
407 | , padapter->bDriverStopped |
408 | , padapter->bSurpriseRemoved | |
409 | , padapter->bup | |
410 | , padapter->hw_init_completed | |
411 | ); | |
412 | ||
413 | status = _SUCCESS; | |
414 | ||
415 | free_hal_data: | |
dc2f9db9 | 416 | if (status != _SUCCESS) |
c2478d39 | 417 | kfree(padapter->HalData); |
c2478d39 LF |
418 | free_adapter: |
419 | if (status != _SUCCESS) { | |
420 | if (pnetdev) | |
421 | rtw_free_netdev(pnetdev); | |
2c10efbd | 422 | else |
03bd6aea | 423 | vfree(padapter); |
c2478d39 LF |
424 | padapter = NULL; |
425 | } | |
426 | exit: | |
427 | return padapter; | |
428 | } | |
429 | ||
430 | static void rtw_usb_if1_deinit(struct adapter *if1) | |
431 | { | |
432 | struct net_device *pnetdev = if1->pnetdev; | |
433 | struct mlme_priv *pmlmepriv = &if1->mlmepriv; | |
434 | ||
435 | if (check_fwstate(pmlmepriv, _FW_LINKED)) | |
436 | rtw_disassoc_cmd(if1, 0, false); | |
437 | ||
438 | #ifdef CONFIG_88EU_AP_MODE | |
439 | free_mlme_ap_info(if1); | |
440 | #endif | |
441 | ||
ac66b628 LC |
442 | if (pnetdev) |
443 | unregister_netdev(pnetdev); /* will call netdev_close() */ | |
444 | ||
0a0796eb | 445 | rtl88eu_mon_deinit(if1->pmondev); |
c2478d39 LF |
446 | rtw_cancel_all_timer(if1); |
447 | ||
448 | rtw_dev_unload(if1); | |
9aa39bc4 | 449 | pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n", |
c2478d39 | 450 | if1->hw_init_completed); |
c2478d39 | 451 | rtw_free_drv_sw(if1); |
a4e320b7 | 452 | rtw_free_netdev(pnetdev); |
c2478d39 LF |
453 | } |
454 | ||
455 | static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) | |
456 | { | |
457 | struct adapter *if1 = NULL; | |
c2478d39 LF |
458 | struct dvobj_priv *dvobj; |
459 | ||
c2478d39 LF |
460 | /* Initialize dvobj_priv */ |
461 | dvobj = usb_dvobj_init(pusb_intf); | |
2e48f0df | 462 | if (!dvobj) { |
c2478d39 LF |
463 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, |
464 | ("initialize device object priv Failed!\n")); | |
465 | goto exit; | |
466 | } | |
467 | ||
468 | if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid); | |
2e48f0df | 469 | if (!if1) { |
9aa39bc4 | 470 | pr_debug("rtw_init_primarystruct adapter Failed!\n"); |
c2478d39 LF |
471 | goto free_dvobj; |
472 | } | |
473 | ||
e0732f84 | 474 | return 0; |
c2478d39 | 475 | |
c2478d39 | 476 | free_dvobj: |
e0732f84 | 477 | usb_dvobj_deinit(pusb_intf); |
c2478d39 | 478 | exit: |
e0732f84 | 479 | return -ENODEV; |
c2478d39 LF |
480 | } |
481 | ||
482 | /* | |
483 | * dev_remove() - our device is being removed | |
484 | */ | |
485 | /* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */ | |
486 | static void rtw_dev_remove(struct usb_interface *pusb_intf) | |
487 | { | |
488 | struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); | |
489 | struct adapter *padapter = dvobj->if1; | |
490 | ||
9aa39bc4 | 491 | pr_debug("+rtw_dev_remove\n"); |
c2478d39 LF |
492 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n")); |
493 | ||
c824795c | 494 | if (!pusb_intf->unregistering) |
c2478d39 LF |
495 | padapter->bSurpriseRemoved = true; |
496 | ||
497 | rtw_pm_set_ips(padapter, IPS_NONE); | |
498 | rtw_pm_set_lps(padapter, PS_MODE_ACTIVE); | |
499 | ||
500 | LeaveAllPowerSaveMode(padapter); | |
501 | ||
502 | rtw_usb_if1_deinit(padapter); | |
503 | ||
504 | usb_dvobj_deinit(pusb_intf); | |
505 | ||
506 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n")); | |
9aa39bc4 | 507 | pr_debug("-r871xu_dev_remove, done\n"); |
c2478d39 LF |
508 | } |
509 | ||
5e2b1f15 | 510 | static struct usb_driver rtl8188e_usb_drv = { |
511 | .name = "r8188eu", | |
512 | .probe = rtw_drv_init, | |
513 | .disconnect = rtw_dev_remove, | |
514 | .id_table = rtw_usb_id_tbl, | |
515 | .suspend = rtw_suspend, | |
516 | .resume = rtw_resume, | |
517 | .reset_resume = rtw_resume, | |
518 | }; | |
519 | ||
774cce1e | 520 | module_usb_driver(rtl8188e_usb_drv) |