usb.cpp
1 #include "usb.h" 2 3 #include <map> 4 #include <list> 5 using std::list; 6 using std::map; 7 8 #include "app_usbd_serial_num.h" 9 #include "nrf_drv_clock.h" 10 11 #include "usb_log_module.ii" 12 13 namespace usb 14 { 15 namespace device 16 { 17 namespace 18 { 19 bool initialized = false; 20 bool enabled = false; 21 bool connected = false; 22 bool supportsPowerDetection = false; 23 map<const app_usbd_class_inst_t*, const class_info_t*> classRegistry; 24 void UsbdEventHandler(app_usbd_event_type_t event); 25 void UsbdAppendAllClasses(); 26 static const app_usbd_config_t usbd_config = { 27 .ev_state_proc = UsbdEventHandler 28 }; 29 list<Listener*> eventListeners; 30 } // namespace 31 32 bool Initialize(bool _supportsPowerDetection /*= true*/) 33 { 34 if (initialized) 35 { 36 return true; 37 } 38 39 app_usbd_serial_num_generate(); 40 app_usbd_product_strings_generate(); 41 42 ret_code_t ret = app_usbd_init(&usbd_config); 43 APP_ERROR_CHECK(ret); 44 45 if (ret != NRF_SUCCESS) 46 { 47 return false; 48 } 49 50 supportsPowerDetection = _supportsPowerDetection; 51 52 NRF_LOG_INFO("USB initialized."); 53 54 initialized = true; 55 return true; 56 } 57 58 bool IsInitialized() 59 { 60 return initialized; 61 } 62 63 bool Enable() 64 { 65 if (enabled) 66 { 67 return true; 68 } 69 70 UsbdAppendAllClasses(); 71 72 if (supportsPowerDetection) 73 { 74 ret_code_t ret = app_usbd_power_events_enable(); 75 APP_ERROR_CHECK(ret); 76 77 if (ret != NRF_SUCCESS) 78 { 79 NRF_LOG_ERROR("Unable to enable power events."); 80 return false; 81 } 82 else 83 { 84 NRF_LOG_INFO("USB power events enabled."); 85 } 86 } 87 else 88 { 89 NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now"); 90 91 app_usbd_enable(); 92 app_usbd_start(); 93 connected = true; 94 95 NRF_LOG_INFO("USB enabled."); 96 } 97 98 return true; 99 } 100 101 bool Disable() 102 { 103 if (enabled == false) 104 { 105 return true; 106 } 107 108 app_usbd_stop(); 109 app_usbd_disable(); 110 app_usbd_class_remove_all(); 111 112 NRF_LOG_INFO("USB disabled."); 113 114 enabled = false; 115 return true; 116 } 117 118 bool IsEnabled() 119 { 120 return enabled; 121 } 122 123 bool RegisterDeviceClass(const class_info_t* deviceClass) 124 { 125 if (deviceClass == nullptr) 126 { 127 NRF_LOG_ERROR("deviceClass cannot be nullptr."); 128 return false; 129 } 130 131 if (classRegistry.find(deviceClass->classInstance) != classRegistry.end()) 132 { 133 NRF_LOG_WARNING("Failed to register new device class, that class is already registered."); 134 return false; 135 } 136 137 // store the class in the registry to append later 138 classRegistry[deviceClass->classInstance] = deviceClass; 139 return true; 140 } 141 142 bool RegisterListener(Listener* listener) 143 { 144 eventListeners.push_back(listener); 145 return true; 146 } 147 148 void Update() 149 { 150 while (app_usbd_event_queue_process()) 151 { 152 /* Nothing to do */ 153 } 154 } 155 156 const uint8_t* const GetSerialNumber() 157 { 158 extern uint8_t g_extern_serial_number[]; 159 return g_extern_serial_number; 160 } 161 162 /// 163 /// File-local functions follow. 164 /// 165 166 namespace 167 { 168 void UsbdEventHandler(app_usbd_event_type_t event) 169 { 170 #define USB_RAISE_LISTENER_EVENT(eventFn) \ 171 if (eventListeners.size() > 0) { \ 172 auto it = eventListeners.begin(); \ 173 while (it != eventListeners.end()) { \ 174 (*it++)->eventFn(event); } } 175 176 //USB_RAISE_LISTENER_EVENT(PreUsbEvent); 177 178 switch (event) 179 { 180 case APP_USBD_EVT_DRV_SUSPEND: 181 break; 182 case APP_USBD_EVT_DRV_RESUME: 183 break; 184 case APP_USBD_EVT_STARTED: 185 break; 186 case APP_USBD_EVT_STOPPED: 187 NRF_LOG_INFO("USB stopped, disabling driver."); 188 app_usbd_disable(); 189 USB_RAISE_LISTENER_EVENT(UsbDidDisable); 190 break; 191 case APP_USBD_EVT_POWER_DETECTED: 192 NRF_LOG_INFO("USB power detected, enabling driver."); 193 194 if (!nrf_drv_usbd_is_enabled()) 195 { 196 USB_RAISE_LISTENER_EVENT(UsbWillEnable); 197 app_usbd_enable(); 198 } 199 break; 200 case APP_USBD_EVT_POWER_REMOVED: 201 NRF_LOG_INFO("USB power removed, switching to disconnected state."); 202 app_usbd_stop(); 203 connected = false; 204 break; 205 case APP_USBD_EVT_POWER_READY: 206 NRF_LOG_INFO("USB ready! Switching to connected state."); 207 app_usbd_start(); 208 connected = true; 209 break; 210 default: 211 break; 212 } 213 214 //USB_RAISE_LISTENER_EVENT(PostUsbEvent); 215 } 216 217 void UsbdAppendAllClasses() 218 { 219 auto it = classRegistry.begin(); 220 221 while (it != classRegistry.end()) 222 { 223 const class_info_t* deviceClass = (*it).second; 224 ret_code_t ret = app_usbd_class_append(deviceClass->classInstance); 225 APP_ERROR_CHECK(ret); 226 227 if (ret == NRF_SUCCESS) 228 { 229 NRF_LOG_INFO("Registered USB device class `%s`.", deviceClass->name); 230 } 231 else 232 { 233 NRF_LOG_WARNING("Failed to registered USB device class `%s`.", deviceClass->name); 234 } 235 236 it++; 237 } 238 } 239 } 240 241 } // namespace device 242 } // namespace Usb