static void usb_hub_port_setup(void *data) { struct usbdevice_s *usbdev = data; struct usbhub_s *hub = usbdev->hub; u32 port = usbdev->port; for (;;) { // Detect if device present (and possibly start reset) int ret = hub->op->detect(hub, port); if (ret > 0) // Device connected. break; if (ret < 0 || timer_check(hub->detectend)) // No device found. goto done; msleep(5); } // XXX - wait USB_TIME_ATTDB time? // Reset port and determine device speed mutex_lock(&hub->cntl->resetlock); int ret = hub->op->reset(hub, port); if (ret < 0) // Reset failed goto resetfail; usbdev->speed = ret; // Set address of port ret = usb_set_address(usbdev); if (ret) { hub->op->disconnect(hub, port); goto resetfail; } mutex_unlock(&hub->cntl->resetlock); // Configure the device int count = configure_usb_device(usbdev); usb_free_pipe(usbdev, usbdev->defpipe); if (!count) hub->op->disconnect(hub, port); hub->devcount += count; done: hub->threads--; free(usbdev); return; resetfail: mutex_unlock(&hub->cntl->resetlock); goto done; }
/* * 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); }
//! This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! If the received request is not supported or a non-standard USB request, the function //! will call the custom decoding function in usb_specific_request module. //! //! @note List of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bRequest; Usb_reset_endpoint_fifo_access(EP_CONTROL); bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8); bRequest = Usb_read_endpoint_data(EP_CONTROL, 8); switch (bRequest) { case GET_DESCRIPTOR: if (bmRequestType == 0x80) usb_get_descriptor(); else goto unsupported_request; break; case GET_CONFIGURATION: if (bmRequestType == 0x80) usb_get_configuration(); else goto unsupported_request; break; case SET_ADDRESS: if (bmRequestType == 0x00) usb_set_address(); else goto unsupported_request; break; case SET_CONFIGURATION: if (bmRequestType == 0x00) usb_set_configuration(); else goto unsupported_request; break; case CLEAR_FEATURE: if (bmRequestType <= 0x02) usb_clear_feature(); else goto unsupported_request; break; case SET_FEATURE: if (bmRequestType <= 0x02) usb_set_feature(); else goto unsupported_request; break; case GET_STATUS: if (0x7F < bmRequestType && bmRequestType <= 0x82) usb_get_status(); else goto unsupported_request; break; case GET_INTERFACE: if (bmRequestType == 0x81) { if(!usb_get_interface()) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); } } else goto unsupported_request; break; case SET_INTERFACE: if (bmRequestType == 0x01) usb_set_interface(); else goto unsupported_request; break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< unsupported request => call to user read request unsupported_request: if (!usb_user_read_request(bmRequestType, bRequest)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); } break; } }
static void usb_setup_set_address(int adr) { usb_set_address(adr); usb_state = adr ? STATE_ADDRESS : STATE_DEFAULT; usb_status_ack(DIR_TX); }
void main() { // mod, added to patch config bits patch_config(); output_high(LEDR); output_low(LEDG); usb_init(); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); set_timer0(0x8ad0); enable_interrupts(GLOBAL); enable_interrupts(INT_TIMER0); while(1) { #if defined (BOARD_AVRUSB12_32) //Mod here we check pin status to see if we must reset device if(!input(PIN_B7)) { delay_ms(25); //debounce if(!input(PIN_B7)) { //its a press output_bit(LEDG,1); delay_ms(500); //for long press detection, if(!input(PIN_B7)) { //its still a press after 1 sec PINRST_BTL(); //reset device } output_bit(LEDG,0); } } #endif usb_task(); usb_isr(); if(DelayCount) continue; if(Connect) { if(UADDR != HubAddress) { usb_set_address(HubAddress); } DevicePort = Connect; port_status[Connect - 1] = PORT_FULL; port_change[Connect - 1] = C_PORT_CONN; TxBuf[0] = 1 << Connect; if(Force0DTS) usb_put_packet(1, TxBuf, 1, 0); else usb_put_packet(1, TxBuf, 1, USB_DTS_TOGGLE); Connect = 0; Force0DTS = 0; } if(Reset) { TxBuf[0] = 1 << Reset; usb_put_packet(1, TxBuf, 1, USB_DTS_TOGGLE); Reset = 0; } if(Disconnect) { if(UADDR != HubAddress) usb_set_address(HubAddress); DevicePort = Disconnect; port_status[Disconnect - 1] = PORT_EMPTY; port_change[Disconnect - 1] = C_PORT_CONN; TxBuf[0] = 1 << Disconnect; usb_put_packet(1, TxBuf, 1, USB_DTS_TOGGLE); Disconnecting = Disconnect; Disconnect = 0; } if(WaitJig) { if(WaitJig == 1) { if(usb_kbhit(2)) { unsigned char c; Chirp(); c = usb_get_packet(2, TxBuf, 8); nJigs++; EP_BDxST_I(1) = 0x40; //Clear IN endpoint if(nJigs == 8) { nJigs = 0; WaitJig = 2; Delay10ms(50); } } } else { int n = 0; for(n = 0; n < 8; ++n) { TxBuf[n] = jig_response[8 * nJigs + n]; } if(usb_put_packet(1, TxBuf, 8, nJigs == 0 ? 0 : USB_DTS_TOGGLE)) { Delay10ms(1); nJigs++; Chirp(); if(nJigs == 8) { nJigs = 0; WaitJig = 0; Delay10ms(15); Disconnect = 3; } } } } if(Address != -1) { delay_ms(1); usb_set_address(Address); Address = -1; } } }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @param none //! //! @return none //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request if(usb_user_read_request(bmRequestType, bmRequest) == FALSE) { Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } break; } }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else goto user_read; break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else goto user_read; break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else goto user_read; break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else goto user_read; break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else goto user_read; break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else goto user_read; break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else goto user_read; break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else goto user_read; break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request user_read: usb_user_read_request(bmRequestType, bmRequest); break; } Usb_select_endpoint(EP_CONTROL); // If the receive setup flag hasn't been cleared // by this point then we can assume that we didn't // support this request and should stall. if(Is_usb_receive_setup()) Usb_enable_stall_handshake(); // Clear some flags. Usb_ack_receive_setup(); Usb_ack_receive_out(); Usb_ack_in_ready(); }
/* * Read the SETUP request sent to the default control endpoint * and call the appropriate function. When exiting this * function, the device is ready to manage the next request. * * Supported requests: * GET_DESCRIPTOR * GET_CONFIGURATION * SET_ADDRESS * SET_CONFIGURATION * CLEAR_FEATURE * SET_FEATURE * GET_STATUS */ void OSUsbDeviceImpl::standardProcessRequest(void) { unsigned char bmRequest; bmRequestType = OSUsbDeviceImpl::readByte(); bmRequest = OSUsbDeviceImpl::readByte(); #if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST) OSDeviceDebug::putString("type/req="); OSDeviceDebug::putHex(bmRequestType); OSDeviceDebug::putString("/"); OSDeviceDebug::putHex(bmRequest); OSDeviceDebug::putString(" "); //OSDeviceDebug::putNewLine(); #endif switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { OSUsbDeviceImpl::usb_get_descriptor(); return; } break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); return; } break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); return; } break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); return; } break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); return; } break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); return; } break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); return; } break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); return; } break; case SET_INTERFACE: if (bmRequestType == 0x01) { usb_set_interface(); return; } break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: break; } // for un-supported requests call the specific read request if (OSUsbDeviceImpl::specificProcessReadRequest(bmRequestType, bmRequest)) return; // if nothing worked, reply with stall OSUsbDeviceImpl::Usb_enable_stall_handshake(); OSUsbDeviceImpl::Usb_ack_receive_setup(); }
//! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! void usb_process_request(void) { U8 bmRequestType; U8 bmRequest; Usb_ack_control_out(); bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case SETUP_GET_DESCRIPTOR: if (USB_SETUP_GET_STAND_DEVICE == bmRequestType) { if( usb_get_descriptor() ) return; } break; case SETUP_GET_CONFIGURATION: if (USB_SETUP_GET_STAND_DEVICE == bmRequestType) { usb_get_configuration(); return; } break; case SETUP_SET_ADDRESS: if (USB_SETUP_SET_STAND_DEVICE == bmRequestType) { usb_set_address(); return; } break; case SETUP_SET_CONFIGURATION: if (USB_SETUP_SET_STAND_DEVICE == bmRequestType) { if( usb_set_configuration() ) return; } break; case SETUP_CLEAR_FEATURE: if (usb_clear_feature(bmRequestType)) return; break; case SETUP_SET_FEATURE: if (usb_set_feature(bmRequestType)) return; break; case SETUP_GET_STATUS: if (usb_get_status(bmRequestType)) return; break; case SETUP_GET_INTERFACE: if (USB_SETUP_GET_STAND_INTERFACE == bmRequestType) { if( usb_get_interface() ) return; } break; case SETUP_SET_INTERFACE: if (bmRequestType == USB_SETUP_SET_STAND_INTERFACE) { if( usb_set_interface() ) return; } break; default: break; } // un-supported like standard request => call to user read request if( !usb_user_read_request(bmRequestType, bmRequest) ) { // Request unknow in the specific request list from interface // keep that order (set StallRq/clear RxSetup) or a // OUT request following the SETUP may be acknowledged Usb_enable_stall_handshake(); Usb_ack_receive_setup(); endpoint_status[(EP_CONTROL & MSK_EP_DIR)] = 0x01; } }