[go: nahoru, domu]

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 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20#define _HCI_INTF_C_
21
22#include <osdep_service.h>
23#include <drv_types.h>
24#include <recv_osdep.h>
25#include <xmit_osdep.h>
26#include <hal_intf.h>
27#include <linux/usb.h>
28#include <linux/vmalloc.h>
29#include <osdep_intf.h>
30
31#include <usb_ops_linux.h>
32#include <usb_hal.h>
33#include <rtw_ioctl.h>
34
35int ui_pid[3] = {0, 0, 0};
36
37#define USB_VENDER_ID_REALTEK		0x0bda
38
39/* DID_USB_v916_20130116 */
40static struct usb_device_id rtw_usb_id_tbl[] = {
41	/*=== Realtek demoboard ===*/
42	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */
43	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
44	/*=== Customer ID ===*/
45	/****** 8188EUS ********/
46	{USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */
47	{USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
48	{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
49	{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
50	{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
51	{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
52	{}	/* Terminating entry */
53};
54
55MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
56
57static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
58{
59	int	i;
60	int	status = _FAIL;
61	struct dvobj_priv *pdvobjpriv;
62	struct usb_host_config		*phost_conf;
63	struct usb_config_descriptor	*pconf_desc;
64	struct usb_host_interface	*phost_iface;
65	struct usb_interface_descriptor	*piface_desc;
66	struct usb_host_endpoint	*phost_endp;
67	struct usb_endpoint_descriptor	*pendp_desc;
68	struct usb_device	*pusbd;
69
70
71	pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
72	if (pdvobjpriv == NULL)
73		goto exit;
74
75	pdvobjpriv->pusbintf = usb_intf;
76	pusbd = interface_to_usbdev(usb_intf);
77	pdvobjpriv->pusbdev = pusbd;
78	usb_set_intfdata(usb_intf, pdvobjpriv);
79
80	pdvobjpriv->RtNumInPipes = 0;
81	pdvobjpriv->RtNumOutPipes = 0;
82
83	phost_conf = pusbd->actconfig;
84	pconf_desc = &phost_conf->desc;
85
86	phost_iface = &usb_intf->altsetting[0];
87	piface_desc = &phost_iface->desc;
88
89	pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
90	pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
91	pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
92
93	for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
94		int ep_num;
95		phost_endp = phost_iface->endpoint + i;
96
97		if (phost_endp) {
98			pendp_desc = &phost_endp->desc;
99			ep_num = usb_endpoint_num(pendp_desc);
100
101			if (usb_endpoint_is_bulk_in(pendp_desc)) {
102				pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
103				pdvobjpriv->RtNumInPipes++;
104			} else if (usb_endpoint_is_int_in(pendp_desc)) {
105				pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
106				pdvobjpriv->RtNumInPipes++;
107			} else if (usb_endpoint_is_bulk_out(pendp_desc)) {
108				pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = ep_num;
109				pdvobjpriv->RtNumOutPipes++;
110			}
111			pdvobjpriv->ep_num[i] = ep_num;
112		}
113	}
114
115	if (pusbd->speed == USB_SPEED_HIGH)
116		pdvobjpriv->ishighspeed = true;
117	else
118		pdvobjpriv->ishighspeed = false;
119
120	mutex_init(&pdvobjpriv->usb_vendor_req_mutex);
121	pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL);
122
123	if (!pdvobjpriv->usb_vendor_req_buf)
124		goto free_dvobj;
125
126	usb_get_dev(pusbd);
127
128	status = _SUCCESS;
129
130free_dvobj:
131	if (status != _SUCCESS && pdvobjpriv) {
132		usb_set_intfdata(usb_intf, NULL);
133		kfree(pdvobjpriv);
134		pdvobjpriv = NULL;
135	}
136exit:
137	return pdvobjpriv;
138}
139
140static void usb_dvobj_deinit(struct usb_interface *usb_intf)
141{
142	struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
143
144
145	usb_set_intfdata(usb_intf, NULL);
146	if (dvobj) {
147		/* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
148		if ((dvobj->NumInterfaces != 2 &&
149		    dvobj->NumInterfaces != 3) ||
150		    (dvobj->InterfaceNumber == 1)) {
151			if (interface_to_usbdev(usb_intf)->state !=
152			    USB_STATE_NOTATTACHED) {
153				/* If we didn't unplug usb dongle and
154				 * remove/insert module, driver fails
155				 * on sitesurvey for the first time when
156				 * device is up . Reset usb port for sitesurvey
157				 * fail issue. */
158				DBG_88E("usb attached..., try to reset usb device\n");
159				usb_reset_device(interface_to_usbdev(usb_intf));
160			}
161		}
162
163		kfree(dvobj->usb_vendor_req_buf);
164		mutex_destroy(&dvobj->usb_vendor_req_mutex);
165		kfree(dvobj);
166	}
167
168	usb_put_dev(interface_to_usbdev(usb_intf));
169
170}
171
172static void usb_intf_start(struct adapter *padapter)
173{
174	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_start\n"));
175
176	rtw_hal_inirp_init(padapter);
177
178	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_start\n"));
179}
180
181static void usb_intf_stop(struct adapter *padapter)
182{
183	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
184
185	/* disabel_hw_interrupt */
186	if (!padapter->bSurpriseRemoved) {
187		/* device still exists, so driver can do i/o operation */
188		/* TODO: */
189		RT_TRACE(_module_hci_intfs_c_, _drv_err_,
190			 ("SurpriseRemoved == false\n"));
191	}
192
193	/* cancel in irp */
194	rtw_hal_inirp_deinit(padapter);
195
196	/* cancel out irp */
197	usb_write_port_cancel(padapter);
198
199	/* todo:cancel other irps */
200
201	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
202}
203
204static void rtw_dev_unload(struct adapter *padapter)
205{
206	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
207
208	if (padapter->bup) {
209		DBG_88E("===> rtw_dev_unload\n");
210		padapter->bDriverStopped = true;
211		if (padapter->xmitpriv.ack_tx)
212			rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
213		/* s3. */
214		if (padapter->intf_stop)
215			padapter->intf_stop(padapter);
216		/* s4. */
217		if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
218			rtw_stop_drv_threads(padapter);
219
220		/* s5. */
221		if (!padapter->bSurpriseRemoved) {
222			rtw_hal_deinit(padapter);
223			padapter->bSurpriseRemoved = true;
224		}
225
226		padapter->bup = false;
227	} else {
228		RT_TRACE(_module_hci_intfs_c_, _drv_err_,
229			 ("r871x_dev_unload():padapter->bup == false\n"));
230	}
231
232	DBG_88E("<=== rtw_dev_unload\n");
233
234	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
235}
236
237static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
238{
239	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
240	struct adapter *padapter = dvobj->if1;
241	struct net_device *pnetdev = padapter->pnetdev;
242	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
243	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
244
245	int ret = 0;
246	u32 start_time = jiffies;
247
248
249	DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
250
251	if ((!padapter->bup) || (padapter->bDriverStopped) ||
252	    (padapter->bSurpriseRemoved)) {
253		DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
254			padapter->bup, padapter->bDriverStopped,
255			padapter->bSurpriseRemoved);
256		goto exit;
257	}
258
259	pwrpriv->bInSuspend = true;
260	rtw_cancel_all_timer(padapter);
261	LeaveAllPowerSaveMode(padapter);
262
263	_enter_pwrlock(&pwrpriv->lock);
264	/* s1. */
265	if (pnetdev) {
266		netif_carrier_off(pnetdev);
267		netif_tx_stop_all_queues(pnetdev);
268	}
269
270	/* s2. */
271	rtw_disassoc_cmd(padapter, 0, false);
272
273	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
274	    check_fwstate(pmlmepriv, _FW_LINKED)) {
275		DBG_88E("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
276			__func__, __LINE__,
277			pmlmepriv->cur_network.network.Ssid.Ssid,
278			pmlmepriv->cur_network.network.MacAddress,
279			pmlmepriv->cur_network.network.Ssid.SsidLength,
280			pmlmepriv->assoc_ssid.SsidLength);
281
282		pmlmepriv->to_roaming = 1;
283	}
284	/* s2-2.  indicate disconnect to os */
285	rtw_indicate_disconnect(padapter);
286	/* s2-3. */
287	rtw_free_assoc_resources(padapter, 1);
288	/* s2-4. */
289	rtw_free_network_queue(padapter, true);
290
291	rtw_dev_unload(padapter);
292	_exit_pwrlock(&pwrpriv->lock);
293
294	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
295		rtw_indicate_scan_done(padapter, 1);
296
297	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
298		rtw_indicate_disconnect(padapter);
299
300exit:
301	DBG_88E("<===  %s return %d.............. in %dms\n", __func__
302		, ret, rtw_get_passing_time_ms(start_time));
303
304	return ret;
305}
306
307static int rtw_resume_process(struct adapter *padapter)
308{
309	struct net_device *pnetdev;
310	struct pwrctrl_priv *pwrpriv = NULL;
311	int ret = -1;
312	u32 start_time = jiffies;
313
314	DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
315
316	if (padapter) {
317		pnetdev = padapter->pnetdev;
318		pwrpriv = &padapter->pwrctrlpriv;
319	} else {
320		goto exit;
321	}
322
323	_enter_pwrlock(&pwrpriv->lock);
324	rtw_reset_drv_sw(padapter);
325	pwrpriv->bkeepfwalive = false;
326
327	DBG_88E("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
328	if (pm_netdev_open(pnetdev, true) != 0)
329		goto exit;
330
331	netif_device_attach(pnetdev);
332	netif_carrier_on(pnetdev);
333
334	_exit_pwrlock(&pwrpriv->lock);
335
336	if (padapter->pid[1] != 0) {
337		DBG_88E("pid[1]:%d\n", padapter->pid[1]);
338		rtw_signal_process(padapter->pid[1], SIGUSR2);
339	}
340
341	rtw_roaming(padapter, NULL);
342
343	ret = 0;
344exit:
345	if (pwrpriv)
346		pwrpriv->bInSuspend = false;
347	DBG_88E("<===  %s return %d.............. in %dms\n", __func__,
348		ret, rtw_get_passing_time_ms(start_time));
349
350
351	return ret;
352}
353
354static int rtw_resume(struct usb_interface *pusb_intf)
355{
356	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
357	struct adapter *padapter = dvobj->if1;
358
359	return rtw_resume_process(padapter);
360}
361
362/*
363 * drv_init() - a device potentially for us
364 *
365 * notes: drv_init() is called when the bus driver has located
366 * a card for us to support.
367 *        We accept the new device by returning 0.
368 */
369
370static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
371	struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
372{
373	struct adapter *padapter = NULL;
374	struct net_device *pnetdev = NULL;
375	int status = _FAIL;
376
377	padapter = (struct adapter *)vzalloc(sizeof(*padapter));
378	if (padapter == NULL)
379		goto exit;
380	padapter->dvobj = dvobj;
381	dvobj->if1 = padapter;
382
383	padapter->bDriverStopped = true;
384	mutex_init(&padapter->hw_init_mutex);
385	padapter->chip_type = RTL8188E;
386
387	pnetdev = rtw_init_netdev(padapter);
388	if (pnetdev == NULL)
389		goto free_adapter;
390	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
391	padapter = rtw_netdev_priv(pnetdev);
392
393	/* step 2. hook HalFunc, allocate HalData */
394	hal_set_hal_ops(padapter);
395
396	padapter->intf_start = &usb_intf_start;
397	padapter->intf_stop = &usb_intf_stop;
398
399	/* step read_chip_version */
400	rtw_hal_read_chip_version(padapter);
401
402	/* step usb endpoint mapping */
403	rtw_hal_chip_configure(padapter);
404
405	/* step read efuse/eeprom data and get mac_addr */
406	rtw_hal_read_chip_info(padapter);
407
408	/* step 5. */
409	if (rtw_init_drv_sw(padapter) == _FAIL) {
410		RT_TRACE(_module_hci_intfs_c_, _drv_err_,
411			 ("Initialize driver software resource Failed!\n"));
412		goto free_hal_data;
413	}
414
415#ifdef CONFIG_PM
416	if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
417		dvobj->pusbdev->do_remote_wakeup = 1;
418		pusb_intf->needs_remote_wakeup = 1;
419		device_init_wakeup(&pusb_intf->dev, 1);
420		DBG_88E("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
421		DBG_88E("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
422			device_may_wakeup(&pusb_intf->dev));
423	}
424#endif
425
426	/* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto
427	 * suspend influence */
428	if (usb_autopm_get_interface(pusb_intf) < 0)
429			DBG_88E("can't get autopm:\n");
430
431	/*  alloc dev name after read efuse. */
432	rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
433	rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
434	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
435	DBG_88E("MAC Address from pnetdev->dev_addr =  %pM\n",
436		pnetdev->dev_addr);
437
438	/* step 6. Tell the network stack we exist */
439	if (register_netdev(pnetdev) != 0) {
440		RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n"));
441		goto free_hal_data;
442	}
443
444	DBG_88E("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
445		, padapter->bDriverStopped
446		, padapter->bSurpriseRemoved
447		, padapter->bup
448		, padapter->hw_init_completed
449	);
450
451	status = _SUCCESS;
452
453free_hal_data:
454	if (status != _SUCCESS)
455		kfree(padapter->HalData);
456free_adapter:
457	if (status != _SUCCESS) {
458		if (pnetdev)
459			rtw_free_netdev(pnetdev);
460		else if (padapter)
461			vfree(padapter);
462		padapter = NULL;
463	}
464exit:
465	return padapter;
466}
467
468static void rtw_usb_if1_deinit(struct adapter *if1)
469{
470	struct net_device *pnetdev = if1->pnetdev;
471	struct mlme_priv *pmlmepriv = &if1->mlmepriv;
472
473	if (check_fwstate(pmlmepriv, _FW_LINKED))
474		rtw_disassoc_cmd(if1, 0, false);
475
476#ifdef CONFIG_88EU_AP_MODE
477	free_mlme_ap_info(if1);
478#endif
479
480	if (pnetdev) {
481		/* will call netdev_close() */
482		unregister_netdev(pnetdev);
483		rtw_proc_remove_one(pnetdev);
484	}
485	rtw_cancel_all_timer(if1);
486
487	rtw_dev_unload(if1);
488	DBG_88E("+r871xu_dev_remove, hw_init_completed=%d\n",
489		if1->hw_init_completed);
490	rtw_free_drv_sw(if1);
491	if (pnetdev)
492		rtw_free_netdev(pnetdev);
493}
494
495static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
496{
497	struct adapter *if1 = NULL;
498	int status = _FAIL;
499	struct dvobj_priv *dvobj;
500
501	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
502
503	/* Initialize dvobj_priv */
504	dvobj = usb_dvobj_init(pusb_intf);
505	if (dvobj == NULL) {
506		RT_TRACE(_module_hci_intfs_c_, _drv_err_,
507			 ("initialize device object priv Failed!\n"));
508		goto exit;
509	}
510
511	if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
512	if (if1 == NULL) {
513		DBG_88E("rtw_init_primarystruct adapter Failed!\n");
514		goto free_dvobj;
515	}
516
517	if (ui_pid[1] != 0) {
518		DBG_88E("ui_pid[1]:%d\n", ui_pid[1]);
519		rtw_signal_process(ui_pid[1], SIGUSR2);
520	}
521
522	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-871x_drv - drv_init, success!\n"));
523
524	status = _SUCCESS;
525
526free_dvobj:
527	if (status != _SUCCESS)
528		usb_dvobj_deinit(pusb_intf);
529exit:
530	return status == _SUCCESS ? 0 : -ENODEV;
531}
532
533/*
534 * dev_remove() - our device is being removed
535*/
536/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */
537static void rtw_dev_remove(struct usb_interface *pusb_intf)
538{
539	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
540	struct adapter *padapter = dvobj->if1;
541
542
543	DBG_88E("+rtw_dev_remove\n");
544	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
545
546	if (!pusb_intf->unregistering)
547		padapter->bSurpriseRemoved = true;
548
549	rtw_pm_set_ips(padapter, IPS_NONE);
550	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
551
552	LeaveAllPowerSaveMode(padapter);
553
554	rtw_usb_if1_deinit(padapter);
555
556	usb_dvobj_deinit(pusb_intf);
557
558	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
559	DBG_88E("-r871xu_dev_remove, done\n");
560
561	return;
562}
563
564static struct usb_driver rtl8188e_usb_drv = {
565	.name = "r8188eu",
566	.probe = rtw_drv_init,
567	.disconnect = rtw_dev_remove,
568	.id_table = rtw_usb_id_tbl,
569	.suspend =  rtw_suspend,
570	.resume = rtw_resume,
571	.reset_resume = rtw_resume,
572};
573
574module_usb_driver(rtl8188e_usb_drv)
575