USB PLUG-AND-PLAY Circle supports USB plug-and-play (USB PnP) since release Step43. This file gives some hints on how USB PnP can be used. A Circle application must provide special support for USB PnP, but this is not mandatory. Applications can work without USB PnP too without modification, like it was the case before. A prerequisite for USB PnP on the Raspberry Pi 1-3 and Zero is, that the system option USE_USB_SOF_INTR is defined in the file include/circle/sysconfig.h. USB PnP may work without this option, but this may be not reliable and is not recommended. ENABLE USB PNP An existing non-USB-PnP application has to be modified as follows to enable USB PnP: * The member initializer for the USB host controller device m_USBHCI in CKernel gets an additional third parameter, which must be set to TRUE to enable USB PnP. If it is set to FALSE (default value) the application is not USB-PnP-aware. CKernel::CKernel (void) : ... m_USBHCI (&m_Interrupt, &m_Timer, TRUE), ... * The application has to continuously call m_USBHCI.UpdatePlugAndPlay() in its main loop on core 0. This allows to update the USB device tree and to detect USB device attachments or removes. This method must not be called from IRQ_LEVEL: boolean bUpdated = m_USBHCI.UpdatePlugAndPlay (); * m_USBHCI.UpdatePlugAndPlay() returns a boolean, which is TRUE, when the USB device tree might have been updated. In this case the application can expect new USB devices to appear. The application should try to get a pointer to the device object(s), which it wants to control: if (bUpdated && m_pDevice == 0) { m_pDevice = m_DeviceNameService.GetDevice ("devname", FALSE or TRUE); if (m_pDevice != 0) { m_pDevice->RegisterRemovedHandler (DeviceRemovedHandler, this); ... This is only needed, if the device pointer is not already known. To accomplish this, there should be a member variable in CKernel, which holds the device pointer or is 0, if the pointer is not known. This pointer should be defined "volatile": class CKernel { ... static void DeviceRemovedHandler (CDevice *pDevice, void *pContext); ... CDevice * volatile m_pDevice; ... * With USB PnP enabled, USB device objects may occasionally be destroyed (inside the UpdatePlugAndPlay() method), when the related device is removed from the USB connector. The application should define a static DeviceRemovedHandler() function, which has to be registered (see above) as handler to be called, when the device object is removed: void CKernel::DeviceRemovedHandler (CDevice *pDevice, void *pContext) { CKernel *pThis = (CKernel *) pContext; pThis->m_pDevice = 0; } The removed handler only resets the m_pDevice pointer to 0 in this case, so that the application knows, that there is no device object available at the moment. * Now the application can access the controlled device using the m_pDevice pointer (has to be casted to a pointer to the actual device class), if the pointer is not 0. SOME NOTES * Samples marked with [PnP] in the file sample/README are enabled for USB PnP. Please have a look at these to get more information on how to enable USB PnP in your application! * Currently processed USB requests may fail, when an USB devices is removed and you may get error messages from the USB driver because of this in that moment. These messages can normally be ignored. * USB mass storage devices (e.g. flash drives) must be unmounted before the device can be removed to prevent data loss. This may require some user interaction. The user requests the device removal via an user interface, the application unmounts the file system and gives an information to the user, that the device can be physically removed now. * USB net devices do currently not support USB PnP. This is not needed, because these devices are fixed on-board and cannot be removed.