示例#1
0
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;
}
示例#2
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;
}
示例#3
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);

}
示例#4
0
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;
		}
示例#5
0
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;
}