InterfaceInit.c revision 4fd64dd0c1b9317ffe6fdaf3de788e14df880d8d
1#include "headers.h"
2
3static struct usb_device_id InterfaceUsbtable[] = {
4    { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
5    { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
6    { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) },
7    { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) },
8    { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) },
9
10    { }
11};
12MODULE_DEVICE_TABLE(usb, InterfaceUsbtable);
13
14VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter)
15{
16	INT i = 0;
17	// Wake up the wait_queue...
18	if(psIntfAdapter->psAdapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
19	{
20		psIntfAdapter->psAdapter->DriverState = DRIVER_HALT;
21		wake_up(&psIntfAdapter->psAdapter->LEDInfo.notify_led_event);
22	}
23	reset_card_proc(psIntfAdapter->psAdapter);
24
25	//worst case time taken by the RDM/WRM will be 5 sec. will check after every 100 ms
26	//to accertain the device is not being accessed. After this No RDM/WRM should be made.
27	while(psIntfAdapter->psAdapter->DeviceAccess)
28	{
29		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Device is being Accessed \n");
30		msleep(100);
31	}
32	/* Free interrupt URB */
33	//psIntfAdapter->psAdapter->device_removed = TRUE;
34	if(psIntfAdapter->psInterruptUrb)
35	{
36		usb_free_urb(psIntfAdapter->psInterruptUrb);
37	}
38
39	/* Free transmit URBs */
40	for(i = 0; i < MAXIMUM_USB_TCB; i++)
41	{
42		if(psIntfAdapter->asUsbTcb[i].urb  != NULL)
43		{
44			usb_free_urb(psIntfAdapter->asUsbTcb[i].urb);
45			psIntfAdapter->asUsbTcb[i].urb = NULL;
46		}
47	}
48	/* Free receive URB and buffers */
49	for(i = 0; i < MAXIMUM_USB_RCB; i++)
50	{
51		if (psIntfAdapter->asUsbRcb[i].urb != NULL)
52		{
53			kfree(psIntfAdapter->asUsbRcb[i].urb->transfer_buffer);
54			usb_free_urb(psIntfAdapter->asUsbRcb[i].urb);
55			psIntfAdapter->asUsbRcb[i].urb = NULL;
56		}
57	}
58	AdapterFree(psIntfAdapter->psAdapter);
59}
60
61VOID ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
62{
63	ULONG ulReg = 0;
64
65// Program EP2 MAX_PKT_SIZE
66	ulReg = ntohl(EP2_MPS_REG);
67	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x128,4,TRUE);
68	ulReg = ntohl(EP2_MPS);
69	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x12C,4,TRUE);
70
71	ulReg = ntohl(EP2_CFG_REG);
72	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x132,4,TRUE);
73	if(((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE)
74	{
75		ulReg = ntohl(EP2_CFG_INT);
76		BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x136,4,TRUE);
77	}
78	else
79	{
80// USE BULK EP as TX in FS mode.
81		ulReg = ntohl(EP2_CFG_BULK);
82		BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x136,4,TRUE);
83	}
84
85
86// Program EP4 MAX_PKT_SIZE.
87	ulReg = ntohl(EP4_MPS_REG);
88	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x13C,4,TRUE);
89	ulReg = ntohl(EP4_MPS);
90	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x140,4,TRUE);
91
92//	Program TX EP as interrupt (Alternate Setting)
93	if( rdmalt(Adapter,0x0F0110F8, (PUINT)&ulReg,4))
94	{
95		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reading of Tx EP is failing");
96		return ;
97	}
98	ulReg |= 0x6;
99
100	ulReg = ntohl(ulReg);
101	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1CC,4,TRUE);
102
103	ulReg = ntohl(EP4_CFG_REG);
104	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1C8,4,TRUE);
105// Program ISOCHRONOUS EP size to zero.
106	ulReg = ntohl(ISO_MPS_REG);
107	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1D2,4,TRUE);
108	ulReg = ntohl(ISO_MPS);
109	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1D6,4,TRUE);
110
111// Update EEPROM Version.
112// Read 4 bytes from 508 and modify 511 and 510.
113//
114	ReadBeceemEEPROM(Adapter,0x1FC,(PUINT)&ulReg);
115	ulReg &= 0x0101FFFF;
116	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1FC,4,TRUE);
117//
118//Update length field if required. Also make the string NULL terminated.
119//
120	ReadBeceemEEPROM(Adapter,0xA8,(PUINT)&ulReg);
121	if((ulReg&0x00FF0000)>>16 > 0x30)
122	{
123		ulReg = (ulReg&0xFF00FFFF)|(0x30<<16);
124		BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0xA8,4,TRUE);
125	}
126	ReadBeceemEEPROM(Adapter,0x148,(PUINT)&ulReg);
127	if((ulReg&0x00FF0000)>>16 > 0x30)
128	{
129		ulReg = (ulReg&0xFF00FFFF)|(0x30<<16);
130		BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x148,4,TRUE);
131	}
132	ulReg = 0;
133	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x122,4,TRUE);
134	ulReg = 0;
135	BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1C2,4,TRUE);
136
137}
138
139static int
140usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
141{
142	struct usb_device *udev = interface_to_usbdev (intf);
143	int retval;
144	PMINI_ADAPTER psAdapter;
145	PS_INTERFACE_ADAPTER psIntfAdapter;
146	struct net_device *ndev;
147
148	/* Reserve one extra queue for the bit-bucket */
149	ndev = alloc_etherdev_mq(sizeof(MINI_ADAPTER), NO_OF_QUEUES+1);
150	if(ndev == NULL) {
151		dev_err(&udev->dev, DRV_NAME ": no memory for device\n");
152		return -ENOMEM;
153	}
154
155	SET_NETDEV_DEV(ndev, &intf->dev);
156
157	psAdapter = netdev_priv(ndev);
158	psAdapter->dev = ndev;
159
160    /* Init default driver debug state */
161
162	psAdapter->stDebugState.debug_level = DBG_LVL_CURR;
163	psAdapter->stDebugState.type = DBG_TYPE_INITEXIT;
164
165    /* Technically, one can start using BCM_DEBUG_PRINT after this point.
166	 * However, realize that by default the Type/Subtype bitmaps are all zero now;
167	 * so no prints will actually appear until the TestApp turns on debug paths via
168	 * the ioctl(); so practically speaking, in early init, no logging happens.
169	 *
170	 * A solution (used below): we explicitly set the bitmaps to 1 for Type=DBG_TYPE_INITEXIT
171	 * and ALL subtype's of the same. Now all bcm debug statements get logged, enabling debug
172	 * during early init.
173	 * Further, we turn this OFF once init_module() completes.
174	 */
175
176    psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xff;
177	BCM_SHOW_DEBUG_BITMAP(psAdapter);
178
179	retval = InitAdapter(psAdapter);
180	if(retval)
181	{
182		dev_err(&udev->dev, DRV_NAME ": InitAdapter Failed\n");
183		AdapterFree(psAdapter);
184		return retval;
185	}
186
187	/* Allocate interface adapter structure */
188	psIntfAdapter = kzalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL);
189	if (psIntfAdapter == NULL)
190	{
191		dev_err(&udev->dev, DRV_NAME ": no memory for Interface adapter\n");
192		AdapterFree (psAdapter);
193		return -ENOMEM;
194	}
195
196	psAdapter->pvInterfaceAdapter = psIntfAdapter;
197	psIntfAdapter->psAdapter = psAdapter;
198
199	/* Store usb interface in Interface Adapter */
200	psIntfAdapter->interface = intf;
201	usb_set_intfdata(intf, psIntfAdapter);
202
203	BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%p",psIntfAdapter);
204	retval = InterfaceAdapterInit(psIntfAdapter);
205	if(retval)
206	{
207		/* If the Firmware/Cfg File is not present
208 		 * then return success, let the application
209 		 * download the files.
210 		 */
211		if(-ENOENT == retval){
212			BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "File Not Found, Use App to Download\n");
213			return STATUS_SUCCESS;
214		}
215		BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapterInit Failed \n");
216		usb_set_intfdata(intf, NULL);
217		udev = interface_to_usbdev (intf);
218		usb_put_dev(udev);
219		InterfaceAdapterFree(psIntfAdapter);
220		return retval ;
221	}
222	if(psAdapter->chip_id > T3)
223	{
224		uint32_t uiNackZeroLengthInt=4;
225		if(wrmalt(psAdapter, DISABLE_USB_ZERO_LEN_INT, &uiNackZeroLengthInt, sizeof(uiNackZeroLengthInt)))
226		{
227			return -EIO;;
228		}
229	}
230
231	/* Check whether the USB-Device Supports remote Wake-Up */
232	if(USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes)
233	{
234		/* If Suspend then only support dynamic suspend */
235		if(psAdapter->bDoSuspend)
236		{
237#ifdef CONFIG_PM
238			udev->autosuspend_delay = 0;
239			intf->needs_remote_wakeup = 1;
240#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
241 			udev->autosuspend_disabled = 0;
242#else
243			usb_enable_autosuspend(udev);
244#endif
245 			device_init_wakeup(&intf->dev,1);
246#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
247 			usb_autopm_disable(intf);
248#endif
249			INIT_WORK(&psIntfAdapter->usbSuspendWork, putUsbSuspend);
250			BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Enabling USB Auto-Suspend\n");
251#endif
252		}
253		else
254		{
255			intf->needs_remote_wakeup = 0;
256#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
257 			udev->autosuspend_disabled = 1;
258#else
259			usb_disable_autosuspend(udev);
260#endif
261		}
262	}
263
264    psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0x0;
265    return retval;
266}
267
268static void usbbcm_disconnect (struct usb_interface *intf)
269{
270	PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
271	PMINI_ADAPTER psAdapter = NULL;
272	struct usb_device       *udev = NULL;
273    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
274
275	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usb disconnected");
276	if(intf == NULL)
277	{
278		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf pointer is NULL");
279		return;
280	}
281	psIntfAdapter = usb_get_intfdata(intf);
282	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%p",psIntfAdapter);
283	if(psIntfAdapter == NULL)
284	{
285		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapter pointer is NULL");
286		return;
287	}
288	psAdapter = psIntfAdapter->psAdapter;
289	if(psAdapter->bDoSuspend)
290		intf->needs_remote_wakeup = 0;
291
292	psAdapter->device_removed = TRUE ;
293	usb_set_intfdata(intf, NULL);
294	InterfaceAdapterFree(psIntfAdapter);
295	udev = interface_to_usbdev (intf);
296	usb_put_dev(udev);
297}
298
299static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
300{
301	int i = 0;
302	for(i = 0; i < MAXIMUM_USB_TCB; i++)
303	{
304		if((psIntfAdapter->asUsbTcb[i].urb =
305				usb_alloc_urb(0, GFP_KERNEL)) == NULL)
306		{
307			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Tx urb for index %d", i);
308			return -ENOMEM;
309		}
310	}
311
312	for(i = 0; i < MAXIMUM_USB_RCB; i++)
313	{
314		if ((psIntfAdapter->asUsbRcb[i].urb =
315				usb_alloc_urb(0, GFP_KERNEL)) == NULL)
316		{
317			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx urb for index %d", i);
318			return -ENOMEM;
319		}
320		if((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
321			kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL)
322		{
323			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx buffer for index %d", i);
324			return -ENOMEM;
325		}
326		psIntfAdapter->asUsbRcb[i].urb->transfer_buffer_length = MAX_DATA_BUFFER_SIZE;
327	}
328	return 0;
329}
330
331
332
333static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter)
334{
335	INT value = 0;
336	UINT status = STATUS_SUCCESS;
337
338	status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter);
339	if(status != STATUS_SUCCESS)
340	{
341		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "InitCardAndDownloadFirmware failed.\n");
342		return status;
343	}
344	if(TRUE == psIntfAdapter->psAdapter->fw_download_done)
345	{
346
347		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Sending first interrupt URB down......");
348		if(StartInterruptUrb(psIntfAdapter))
349		{
350			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Cannot send interrupt in URB");
351		}
352		//now register the cntrl interface.
353		//after downloading the f/w waiting for 5 sec to get the mailbox interrupt.
354
355		psIntfAdapter->psAdapter->waiting_to_fw_download_done = FALSE;
356		value = wait_event_timeout(psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue,
357					psIntfAdapter->psAdapter->waiting_to_fw_download_done, 5*HZ);
358
359		if(value == 0)
360		{
361			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Mailbox Interrupt has not reached to Driver..");
362		}
363		else
364		{
365			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Got the mailbox interrupt ...Registering control interface...\n ");
366		}
367		if(register_control_device_interface(psIntfAdapter->psAdapter) < 0)
368		{
369			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Register Control Device failed...");
370			return -EIO;
371		}
372	}
373	return 0;
374}
375
376
377static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
378{
379	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
380}
381
382static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
383{
384	return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
385}
386
387static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
388{
389	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
390}
391
392static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
393{
394	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
395}
396
397static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
398{
399	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
400		USB_ENDPOINT_XFER_BULK);
401}
402
403static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
404{
405	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
406		USB_ENDPOINT_XFER_CONTROL);
407}
408
409static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
410{
411	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
412		USB_ENDPOINT_XFER_INT);
413}
414
415static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
416{
417	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
418		USB_ENDPOINT_XFER_ISOC);
419}
420
421static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
422{
423	return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd));
424}
425
426static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
427{
428	return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd));
429}
430
431static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
432{
433	return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd));
434}
435
436static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
437{
438	return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd));
439}
440
441static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
442{
443	return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd));
444}
445
446static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
447{
448	return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd));
449}
450
451INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
452{
453	struct usb_host_interface *iface_desc;
454	struct usb_endpoint_descriptor *endpoint;
455	size_t buffer_size;
456	ULONG value;
457	INT retval = 0;
458	INT usedIntOutForBulkTransfer = 0 ;
459	BOOLEAN bBcm16 = FALSE;
460	UINT uiData = 0;
461
462	/* Store the usb dev into interface adapter */
463	psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(
464								psIntfAdapter->interface));
465
466	if((psIntfAdapter->udev->speed == USB_SPEED_HIGH))
467	{
468		psIntfAdapter->bHighSpeedDevice = TRUE ;
469		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO HIGH_SPEED ");
470	}
471	else
472	{
473		psIntfAdapter->bHighSpeedDevice = FALSE ;
474		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO FULL_SPEED ");
475	}
476
477	psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
478	psIntfAdapter->psAdapter->interface_wrm = BcmWRM;
479
480	if(rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG, (PUINT)&(psIntfAdapter->psAdapter->chip_id), sizeof(UINT)) < 0)
481	{
482		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n");
483		return STATUS_FAILURE;
484	}
485    if(0xbece3200==(psIntfAdapter->psAdapter->chip_id&~(0xF0)))
486	{
487		psIntfAdapter->psAdapter->chip_id=(psIntfAdapter->psAdapter->chip_id&~(0xF0));
488	}
489
490	BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "First RDM Chip ID 0x%lx\n", psIntfAdapter->psAdapter->chip_id);
491
492    iface_desc = psIntfAdapter->interface->cur_altsetting;
493	//print_usb_interface_desc(&(iface_desc->desc));
494
495	if(psIntfAdapter->psAdapter->chip_id == T3B)
496	{
497
498		//
499		//T3B device will have EEPROM,check if EEPROM is proper and BCM16 can be done or not.
500		//
501		BeceemEEPROMBulkRead(psIntfAdapter->psAdapter,&uiData,0x0,4);
502		if(uiData == BECM)
503		{
504			bBcm16 = TRUE;
505		}
506		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Number of Altsetting aviailable for This Modem 0x%x\n", psIntfAdapter->interface->num_altsetting);
507		if(bBcm16 == TRUE)
508		{
509			//selecting alternate setting one as a default setting for High Speed  modem.
510			if(psIntfAdapter->bHighSpeedDevice)
511				retval= usb_set_interface(psIntfAdapter->udev,DEFAULT_SETTING_0,ALTERNATE_SETTING_1);
512			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM16 is Applicable on this dongle");
513			if(retval || (psIntfAdapter->bHighSpeedDevice == FALSE))
514			{
515				usedIntOutForBulkTransfer = EP2 ;
516				endpoint = &iface_desc->endpoint[EP2].desc;
517				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Interface altsetting  got failed or Moemd is configured to FS.hence will work on default setting 0 \n");
518				/*
519				If Modem is high speed device EP2 should be INT OUT End point
520				If Mode is FS then EP2 should be bulk end point
521				*/
522				if(((psIntfAdapter->bHighSpeedDevice ==TRUE ) && (bcm_usb_endpoint_is_int_out(endpoint)== FALSE))
523					||((psIntfAdapter->bHighSpeedDevice == FALSE)&& (bcm_usb_endpoint_is_bulk_out(endpoint)== FALSE)))
524				{
525					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Configuring the EEPROM ");
526					//change the EP2, EP4 to INT OUT end point
527					ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter);
528
529					/*
530					It resets the device and if any thing gets changed in USB descriptor it will show fail and
531					re-enumerate the device
532					*/
533					retval = usb_reset_device(psIntfAdapter->udev);
534					if(retval)
535					{
536						BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n");
537						return retval ;
538					}
539
540				}
541				if((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint))
542				{
543					// Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail.
544					UINT _uiData = ntohl(EP2_CFG_INT);
545					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Reverting Bulk to INT as it is FS MODE");
546					BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter,(PUCHAR)&_uiData,0x136,4,TRUE);
547				}
548			}
549			else
550			{
551				usedIntOutForBulkTransfer = EP4 ;
552				endpoint = &iface_desc->endpoint[EP4].desc;
553				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Choosing AltSetting as a default setting");
554				if( bcm_usb_endpoint_is_int_out(endpoint) == FALSE)
555				{
556					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, " Dongle does not have BCM16 Fix");
557					//change the EP2, EP4 to INT OUT end point and use EP4 in altsetting
558					ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter);
559
560					/*
561					It resets the device and if any thing gets changed in USB descriptor it will show fail and
562					re-enumerate the device
563					*/
564					retval = usb_reset_device(psIntfAdapter->udev);
565					if(retval)
566					{
567						BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n");
568						return retval ;
569					}
570
571				}
572			}
573		}
574	}
575
576	iface_desc = psIntfAdapter->interface->cur_altsetting;
577	//print_usb_interface_desc(&(iface_desc->desc));
578   	BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Current number of endpoints :%x \n", iface_desc->desc.bNumEndpoints);
579    for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value)
580	{
581        endpoint = &iface_desc->endpoint[value].desc;
582		//print_usb_endpoint_descriptor(endpoint);
583
584        if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint))
585        {
586            buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
587            psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
588            psIntfAdapter->sBulkIn.bulk_in_endpointAddr =
589								endpoint->bEndpointAddress;
590	    	psIntfAdapter->sBulkIn.bulk_in_pipe =
591					usb_rcvbulkpipe(psIntfAdapter->udev,
592								psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
593        }
594
595        if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint))
596        {
597
598			psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
599										endpoint->bEndpointAddress;
600	    	psIntfAdapter->sBulkOut.bulk_out_pipe =
601			usb_sndbulkpipe(psIntfAdapter->udev,
602					psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
603        }
604
605        if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint))
606        {
607            buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
608            psIntfAdapter->sIntrIn.int_in_size = buffer_size;
609            psIntfAdapter->sIntrIn.int_in_endpointAddr =
610								endpoint->bEndpointAddress;
611            psIntfAdapter->sIntrIn.int_in_interval = endpoint->bInterval;
612            psIntfAdapter->sIntrIn.int_in_buffer =
613						kmalloc(buffer_size, GFP_KERNEL);
614            if (!psIntfAdapter->sIntrIn.int_in_buffer) {
615                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_in_buffer");
616                return -EINVAL;
617            }
618			//psIntfAdapter->sIntrIn.int_in_pipe =
619        }
620
621        if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint))
622        {
623
624			if( !psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
625				(psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer))
626			{
627				//use first intout end point as a bulk out end point
628            	buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
629            	psIntfAdapter->sBulkOut.bulk_out_size = buffer_size;
630				//printk("\nINT OUT Endpoing buffer size :%x endpoint :%x\n", buffer_size, value +1);
631				psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
632										endpoint->bEndpointAddress;
633	    		psIntfAdapter->sBulkOut.bulk_out_pipe =
634				usb_sndintpipe(psIntfAdapter->udev,
635					psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
636          	  	psIntfAdapter->sBulkOut.int_out_interval = endpoint->bInterval;
637
638			}
639			else if(value == EP6)
640			{
641	            buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
642	            psIntfAdapter->sIntrOut.int_out_size = buffer_size;
643	            psIntfAdapter->sIntrOut.int_out_endpointAddr =
644										endpoint->bEndpointAddress;
645	            psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval;
646	            psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size,
647														GFP_KERNEL);
648	            	if (!psIntfAdapter->sIntrOut.int_out_buffer)
649					{
650	                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_out_buffer");
651	                return -EINVAL;
652            }
653        }
654    }
655	}
656    usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter);
657
658	psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload;
659	psIntfAdapter->psAdapter->bcm_file_readback_from_chip =
660				InterfaceFileReadbackFromChip;
661	psIntfAdapter->psAdapter->interface_transmit = InterfaceTransmitPacket;
662
663	retval = CreateInterruptUrb(psIntfAdapter);
664
665	if(retval)
666	{
667		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cannot create interrupt urb");
668		return retval;
669	}
670
671	retval = AllocUsbCb(psIntfAdapter);
672	if(retval)
673	{
674		return retval;
675	}
676
677
678	return device_run(psIntfAdapter);
679}
680
681static int InterfaceSuspend (struct usb_interface *intf, pm_message_t message)
682{
683	PS_INTERFACE_ADAPTER  psIntfAdapter = usb_get_intfdata(intf);
684	BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=================================\n");
685	//Bcm_kill_all_URBs(psIntfAdapter);
686	psIntfAdapter->bSuspended = TRUE;
687
688	if(TRUE == psIntfAdapter->bPreparingForBusSuspend)
689	{
690		psIntfAdapter->bPreparingForBusSuspend = FALSE;
691
692		if(psIntfAdapter->psAdapter->LinkStatus == LINKUP_DONE)
693		{
694			psIntfAdapter->psAdapter->IdleMode = TRUE ;
695			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Idle Mode..");
696		}
697		else
698		{
699			psIntfAdapter->psAdapter->bShutStatus = TRUE;
700			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Shutdown Mode..");
701		}
702	}
703	psIntfAdapter->psAdapter->bPreparingForLowPowerMode = FALSE;
704
705	//Signaling the control pkt path
706	wake_up(&psIntfAdapter->psAdapter->lowpower_mode_wait_queue);
707
708	return 0;
709}
710
711static int InterfaceResume (struct usb_interface *intf)
712{
713    PS_INTERFACE_ADAPTER  psIntfAdapter = usb_get_intfdata(intf);
714	printk("=================================\n");
715	mdelay(100);
716#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
717 	intf->pm_usage_cnt =1 ;
718#endif
719	psIntfAdapter->bSuspended = FALSE;
720
721	StartInterruptUrb(psIntfAdapter);
722	InterfaceRx(psIntfAdapter);
723	return 0;
724}
725
726static struct usb_driver usbbcm_driver = {
727    .name = "usbbcm",
728    .probe = usbbcm_device_probe,
729    .disconnect = usbbcm_disconnect,
730    .suspend = InterfaceSuspend,
731    .resume = InterfaceResume,
732    .id_table = InterfaceUsbtable,
733    .supports_autosuspend = 1,
734};
735
736struct class *bcm_class;
737
738/*
739Function:				InterfaceInitialize
740
741Description:			This is the hardware specific initialization Function.
742						Registering the driver with NDIS , other device specific NDIS
743						and hardware initializations are done here.
744
745Input parameters:		IN PMINI_ADAPTER Adapter   - Miniport Adapter Context
746
747
748Return:					BCM_STATUS_SUCCESS - If Initialization of the
749						HW Interface was successful.
750						Other           - If an error occured.
751*/
752INT InterfaceInitialize(void)
753{
754	bcm_class = class_create(THIS_MODULE, DRV_NAME);
755	if (IS_ERR(bcm_class)) {
756		printk(KERN_ERR DRV_NAME ": could not create class\n");
757		return PTR_ERR(bcm_class);
758	}
759	return usb_register(&usbbcm_driver);
760}
761
762INT InterfaceExit(void)
763{
764        class_destroy (bcm_class);
765	usb_deregister(&usbbcm_driver);
766	return 0;
767}
768