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