static int rtek_init_device( rtek_softc_t *softc ) { usb_device_descr_t dev_desc; uint16_t vendor_id, product_id; const int *ptr=ID_TBL; int i; usbdev_t *dev = softc->dev; uint8_t val; /* find out which device is connected */ usb_get_device_descriptor( softc->dev, &dev_desc, 0 ); vendor_id = (dev_desc.idVendorHigh << 8) + dev_desc.idVendorLow; product_id = (dev_desc.idProductHigh << 8) + dev_desc.idProductLow; while( *ptr != -1 ) { if( (vendor_id == ptr[0]) && (product_id == ptr[1]) ) { softc->ven_code = ptr[2]; break; } ptr += 3; } if( *ptr == -1 ) { xprintf( "Unrecognized Realtek USB-Ethernet device\n" ); return -1; } /* Reset the adapter */ rtek_set_reg( dev, R_RTEK_CMD, RTEK_RESET ); for( i = 0; i < 10; ++i ) { rtek_get_reg( dev, R_RTEK_CMD, &val, 1 ); if( !(val & RTEK_RESET) ) break; usb_delay_ms( NULL, 1 ); } /* Autoload the internal registers */ rtek_set_reg( dev, R_RTEK_CMD, RTEK_AUTOLOAD ); for( i = 0; i < 50; ++i ) { rtek_get_reg( dev, R_RTEK_CMD, &val, 1 ); if( !(val & RTEK_AUTOLOAD) ) break; usb_delay_ms( NULL, 1 ); } /* Read the adapter's MAC addr */ rtek_get_mac_addr( dev, softc->mac_addr ); /* display adapter info */ xprintf( "%s USB-Ethernet Adapter (%a)\n", VENDOR_NAMES[softc->ven_code], softc->mac_addr); return 0; }
/* * WARNING - If a driver calls usb_reset_device, you should simulate a * disconnect() and probe() for other interfaces you doesn't claim. This * is left up to the driver writer right now. This insures other drivers * have a chance to re-setup their interface. * * Take a look at proc_resetdevice in devio.c for some sample code to * do this. */ int usb_reset_device(struct usb_device *dev) { struct usb_device *parent = dev->parent; struct usb_device_descriptor descriptor; int i, ret, port = -1; DBG_HOST_HUB("### >>> Enter hub.c file --> usb_reset_device function \n"); if (!parent) { err("attempting to reset root hub!"); return -EINVAL; } for (i = 0; i < parent->maxchild; i++) if (parent->children[i] == dev) { port = i; break; } if (port < 0) return -ENOENT; down(&usb_address0_sem); /* Send a reset to the device */ if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { usb_hub_port_disable(parent, port); up(&usb_address0_sem); return(-ENODEV); } /* Reprogram the Address */ ret = usb_set_address(dev); if (ret < 0) { err("USB device not accepting new address (error=%d)", ret); usb_hub_port_disable(parent, port); up(&usb_address0_sem); return ret; } /* Let the SET_ADDRESS settle */ wait_ms(10); up(&usb_address0_sem); /* * Now we fetch the configuration descriptors for the device and * see if anything has changed. If it has, we dump the current * parsed descriptors and reparse from scratch. Then we leave * the device alone for the caller to finish setting up. * * If nothing changed, we reprogram the configuration and then * the alternate settings. */ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor, sizeof(descriptor)); if (ret < 0) return ret; le16_to_cpus(&descriptor.bcdUSB); le16_to_cpus(&descriptor.idVendor); le16_to_cpus(&descriptor.idProduct); le16_to_cpus(&descriptor.bcdDevice); if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) { usb_destroy_configuration(dev); ret = usb_get_device_descriptor(dev); if (ret < sizeof(dev->descriptor)) { if (ret < 0) err("unable to get device descriptor (error=%d)", ret); else err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), ret); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return -EIO; } ret = usb_get_configuration(dev); if (ret < 0) { err("unable to get configuration (error=%d)", ret); usb_destroy_configuration(dev); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->actconfig = dev->config; usb_set_maxpacket(dev); return 1; } ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue); if (ret < 0) { err("failed to set active configuration (error=%d)", ret); return ret; } for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { struct usb_interface *intf = &dev->actconfig->interface[i]; struct usb_interface_descriptor *as = &intf->altsetting[intf->act_altsetting]; ret = usb_set_interface(dev, as->bInterfaceNumber, as->bAlternateSetting); if (ret < 0) { err("failed to set active alternate setting for interface %d (error=%d)", i, ret); return ret; } } return 0; }
static void usbhub_scan_ports(usbdev_t *dev,void *arg) { uint16_t current; uint16_t changed; usbhub_softc_t *softc; int idx; int res; int len; uint8_t *buf; usbdev_t *newdev; usb_driver_t *newdrv; int addr; usb_port_status_t *portstatus; usb_config_descr_t cfgdescr; unsigned int powerondelay; if (!IS_HUB(dev)) return; /* should not happen. */ portstatus = usb_dma_alloc(sizeof(usb_port_status_t)); if (portstatus == NULL) return; /* * We know this is a hub. Get the softc back. */ softc = (usbhub_softc_t *) dev->ud_private; powerondelay = ((unsigned int) softc->uhub_descr.bPowerOnToPowerGood)*2 + 20; /* * Turn on the power to the ports whose power is not yet on. */ for (idx = 0; idx < softc->uhub_nports; idx++) { usbhub_get_port_status(dev,idx+1,portstatus); current = GETUSBFIELD(portstatus,wPortStatus); changed = GETUSBFIELD(portstatus,wPortChange); if (usb_noisy > 1) { printf("BeforePowerup: port %d status %04X changed %04X\n",idx+1,current,changed); } if (!(current & USB_PORT_STATUS_POWER)) { if (usb_noisy > 1) console_log("USB: Powering up bus %d port %d", dev->ud_bus->ub_num,idx+1); usbhub_set_port_feature(dev,idx+1,USB_PORT_FEATURE_POWER); usb_delay_ms(dev->ud_bus,powerondelay); } } /* * Begin exploration at this level. */ for (idx = 0; idx < softc->uhub_nports; idx++) { usbhub_get_port_status(dev,idx+1,portstatus); current = GETUSBFIELD(portstatus,wPortStatus); changed = GETUSBFIELD(portstatus,wPortChange); if (usb_noisy > 0) { printf("USB: Explore: Bus %d Hub %d port %d status %04X changed %04X\n", dev->ud_bus->ub_num, dev->ud_address,idx+1,current,changed); usb_dbg_dumpportstatus(idx+1,portstatus,1); } // if (changed & USB_PORT_STATUS_RESET) { // usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_RESET); // } if (changed & USB_PORT_STATUS_ENABLED) { usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_ENABLE); } if (changed & USB_PORT_STATUS_CONNECT) { /* * A device was either connected or disconnected. * Clear the status change first. */ usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_CONNECTION); if (current & USB_PORT_STATUS_CONNECT) { /* * The device has been CONNECTED. */ console_log("USB: New device connected to bus %d hub %d port %d", dev->ud_bus->ub_num, dev->ud_address,idx+1); /* * Reset the device. Reuse our old port status structure * so we get the latest status. Some devices do not report * lowspeed until they are reset. */ usbhub_reset_device(dev,idx+1,portstatus); current = GETUSBFIELD(portstatus,wPortStatus); changed = GETUSBFIELD(portstatus,wPortChange); /* * Create a device for this port. */ newdev = usb_create_device(dev->ud_bus,(current & USB_PORT_STATUS_LOWSPD) ? 1 : 0); /* * Get the device descriptor. */ res = usb_get_device_descriptor(newdev,&newdev->ud_devdescr,TRUE); if (usb_noisy > 1) usb_dbg_dumpdescriptors(newdev,(uint8_t *) &(newdev->ud_devdescr),8); /* * Set up the max packet size for the control endpoint, * then get the rest of the descriptor. */ usb_set_ep0mps(newdev,newdev->ud_devdescr.bMaxPacketSize0); res = usb_get_device_descriptor(newdev,&newdev->ud_devdescr,FALSE); /* * Obtain a new address and set the address of the * root hub to this address. */ addr = usb_new_address(newdev->ud_bus); res = usb_set_address(newdev,addr); /* * Get the configuration descriptor and all the * associated interface and endpoint descriptors. */ res = usb_get_config_descriptor(newdev,&cfgdescr,0, sizeof(usb_config_descr_t)); if (res != sizeof(usb_config_descr_t)) { printf("[a] usb_get_config_descriptor returns %d\n",res); } len = GETUSBFIELD(&cfgdescr,wTotalLength); buf = usb_dma_alloc(len); res = usb_get_config_descriptor(newdev,(usb_config_descr_t *)buf,0,len); if (res != len) { printf("[b] usb_get_config_descriptor returns %d\n",res); } newdev->ud_cfgdescr = (usb_config_descr_t *) buf; if (usb_noisy > 1) usb_dbg_dumpdescriptors(newdev,buf,len); /* * Point the hub at the devices it owns */ softc->uhub_devices[idx] = newdev; /* * Find the driver for this. It had better be the hub * driver. */ newdrv = usb_find_driver(newdev); /* * Call the attach method. */ if (newdrv) { newdev->ud_drv = newdrv; /* remember driver dispatch in device */ (*(newdrv->udrv_attach))(newdev,newdrv); } } else { /* * The device has been DISCONNECTED. */ console_log("USB: Device disconnected from bus %d hub %d port %d", dev->ud_bus->ub_num, dev->ud_address,idx+1); /* * Recover pointer to device below hub and clear * this pointer. */ newdev = softc->uhub_devices[idx]; /* Get device pointer */ usbhub_markdetached(newdev); /* mark device and all subordinate devices as "removing" */ softc->uhub_devices[idx] = NULL; /* remove device from hub */ /* * Deassign the USB device's address and then * call detach method to free resources. Devices that * do not have drivers will not have any methods. */ if (newdev) { if (newdev->ud_drv) { /* close open pipes, cancel reqs */ usb_destroy_all_pipes(newdev); /* * Try to process the done queue. This will complete any * requests that made it out of the pipes while we were * doing the stuff above. */ usb_poll(newdev->ud_bus); /* Call detach method, clean up device softc */ (*(newdev->ud_drv->udrv_detach))(newdev); } else { if (usb_noisy > 0) { console_log("USB: Detached device on bus %d hub %d port %d " "has no methods", dev->ud_bus->ub_num, dev->ud_address,idx+1); } } if (newdev->ud_cfgdescr) usb_dma_free(newdev->ud_cfgdescr); usb_destroy_device(newdev); } } } } usb_dma_free(portstatus); /* * Queue up a request for the interrupt pipe. This will catch further * changes at this port. */ usbhub_queue_intreq(dev,softc); }
static void usbIRQHandler(uint32_t token) { // we need to mask because GINTSTS is set for a particular interrupt even if it's masked in GINTMSK (GINTMSK just prevents an interrupt being generated) uint32_t status = GET_REG(USB + GINTSTS) & GET_REG(USB + GINTMSK); int process = FALSE; //uartPrintf("<begin interrupt: %x>\r\n", status); if(status) { process = TRUE; } while(process) { if((status & GINTMSK_OTG) == GINTMSK_OTG) { // acknowledge OTG interrupt (these bits are all R_SS_WC which means Write Clear, a write of 1 clears the bits) SET_REG(USB + GOTGINT, GET_REG(USB + GOTGINT)); // acknowledge interrupt (this bit is actually RO, but should've been cleared when we cleared GOTGINT. Still, iBoot pokes it as if it was WC, so we will too) SET_REG(USB + GINTSTS, GINTMSK_OTG); process = TRUE; } else { // we only care about OTG process = FALSE; } if((status & GINTMSK_RESET) == GINTMSK_RESET) { if(usb_state < USBError) { bufferPrintf("usb: reset detected\r\n"); change_state(USBPowered); } int retval = resetUSB(); SET_REG(USB + GINTSTS, GINTMSK_RESET); if(retval) { bufferPrintf("usb: listening for further usb events\r\n"); return; } process = TRUE; } if(((status & GINTMSK_INEP) == GINTMSK_INEP) || ((status & GINTMSK_OEP) == GINTMSK_OEP)) { // aha, got something on one of the endpoints. Now the real fun begins // first, let's get the interrupt status of individual endpoints getEndpointInterruptStatuses(); if(isSetupPhaseDone()) { // recall our earlier receiveControl calls. We now should have 8 bytes of goodness in controlRecvBuffer. USBSetupPacket* setupPacket = (USBSetupPacket*) controlRecvBuffer; uint16_t length; uint32_t totalLength; USBStringDescriptor* strDesc; if(USBSetupPacketRequestTypeType(setupPacket->bmRequestType) != USBSetupPacketVendor) { switch(setupPacket->bRequest) { case USB_GET_DESCRIPTOR: length = setupPacket->wLength; // descriptor type is high, descriptor index is low switch(setupPacket->wValue >> 8) { case USBDeviceDescriptorType: if(length > sizeof(USBDeviceDescriptor)) length = sizeof(USBDeviceDescriptor); memcpy(controlSendBuffer, usb_get_device_descriptor(), length); break; case USBConfigurationDescriptorType: // hopefully SET_ADDRESS was received beforehand to set the speed totalLength = getConfigurationTree(setupPacket->wValue & 0xFF, usb_speed, controlSendBuffer); if(length > totalLength) length = totalLength; break; case USBStringDescriptorType: strDesc = usb_get_string_descriptor(setupPacket->wValue & 0xFF); if(length > strDesc->bLength) length = strDesc->bLength; memcpy(controlSendBuffer, strDesc, length); break; case USBDeviceQualifierDescriptorType: if(length > sizeof(USBDeviceQualifierDescriptor)) length = sizeof(USBDeviceQualifierDescriptor); memcpy(controlSendBuffer, usb_get_device_qualifier_descriptor(), length); break; default: bufferPrintf("Unknown descriptor request: %d\r\n", setupPacket->wValue >> 8); if(usb_state < USBError) { change_state(USBUnknownDescriptorRequest); } } if(usb_state < USBError) { sendControl(controlSendBuffer, length); } break; case USB_SET_ADDRESS: usb_speed = DSTS_GET_SPEED(GET_REG(USB + DSTS)); usb_max_packet_size = packetsizeFromSpeed(usb_speed); SET_REG(USB + DCFG, (GET_REG(USB + DCFG) & ~DCFG_DEVICEADDRMSK) | ((setupPacket->wValue & DCFG_DEVICEADDR_UNSHIFTED_MASK) << DCFG_DEVICEADDR_SHIFT)); // send an acknowledgement sendControl(controlSendBuffer, 0); if(usb_state < USBError) { change_state(USBAddress); } break; case USB_SET_INTERFACE: // send an acknowledgement sendControl(controlSendBuffer, 0); break; case USB_GET_STATUS: // FIXME: iBoot doesn't really care about this status *((uint16_t*) controlSendBuffer) = 0; sendControl(controlSendBuffer, sizeof(uint16_t)); break; case USB_GET_CONFIGURATION: // FIXME: iBoot just puts out a debug message on console for this request. break; case USB_SET_CONFIGURATION: setConfiguration(0); // send an acknowledgment sendControl(controlSendBuffer, 0); if(usb_state < USBError) { change_state(USBConfigured); startHandler(); } break; default: if(usb_state < USBError) { change_state(USBUnknownRequest); } } // get the next SETUP packet receiveControl(controlRecvBuffer, sizeof(USBSetupPacket)); } } else { //uartPrintf("\t<begin callEndpointHandlers>\r\n"); callEndpointHandlers(); //uartPrintf("\t<end callEndpointHandlers>\r\n"); } process = TRUE; }
static int usbOpenDevice(usb_device_handle **device, int vendor, char *vendorName, int product, char *productName) { usb_device_handle *handle = NULL; int errorCode = USB_ERROR_NOTFOUND; static int didUsbInit = 0; int j; int r; if(!didUsbInit){ didUsbInit = 1; usb_init(&ctx); } usb_device **dev_list; int dev_list_len = usb_get_device_list(ctx, &dev_list); for (j=0; j<dev_list_len; ++j) { usb_device *dev = dev_list[j]; struct usb_device_descriptor descriptor; usb_get_device_descriptor(dev, &descriptor); if (descriptor.idVendor == vendor && descriptor.idProduct == product) { char string[256]; /* we need to open the device in order to query strings */ r = usb_open(dev, &handle); if (!handle) { errorCode = USB_ERROR_ACCESS; fprintf(stderr, "%s: Warning: cannot open USB device: %s\n", progname, strerror(usb_to_errno(r))); continue; } errorCode = 0; /* now check whether the names match: */ /* if vendorName not given ignore it (any vendor matches) */ r = usb_get_string_descriptor_ascii(handle, descriptor.iManufacturer & 0xff, string, sizeof(string)); if (r < 0) { if ((vendorName != NULL) && (vendorName[0] != 0)) { errorCode = USB_ERROR_IO; fprintf(stderr, "%s: Warning: cannot query manufacturer for device: %s\n", progname, strerror(usb_to_errno(r))); } } else { if (verbose > 1) fprintf(stderr, "%s: seen device from vendor ->%s<-\n", progname, string); if ((vendorName != NULL) && (vendorName[0] != 0) && (strcmp(string, vendorName) != 0)) errorCode = USB_ERROR_NOTFOUND; } /* if productName not given ignore it (any product matches) */ r = usb_get_string_descriptor_ascii(handle, descriptor.iProduct & 0xff, string, sizeof(string)); if (r < 0) { if ((productName != NULL) && (productName[0] != 0)) { errorCode = USB_ERROR_IO; fprintf(stderr, "%s: Warning: cannot query product for device: %s\n", progname, strerror(usb_to_errno(r))); } } else { if (verbose > 1) fprintf(stderr, "%s: seen product ->%s<-\n", progname, string); if((productName != NULL) && (productName[0] != 0) && (strcmp(string, productName) != 0)) errorCode = USB_ERROR_NOTFOUND; } if (errorCode == 0) break; usb_close(handle); handle = NULL; } } usb_free_device_list(dev_list,1); if (handle != NULL){ errorCode = 0; *device = handle; } return errorCode; }