/ src / usb / usb.cpp
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