@@ -98,6 +98,76 @@ namespace klib::core::mb9bf560l::io {
9898 // struct with information about the state of a endpoint
9999 static inline volatile detail::usb::state state[endpoint_count] = {};
100100
101+ /* *
102+ * @brief Convert a mode to the correct raw value for the usb hardware
103+ *
104+ * @param mode
105+ * @return uint8_t
106+ */
107+ constexpr static uint8_t transfer_type_to_raw (const klib::usb::descriptor::transfer_type type) {
108+ // convert the type to raw data
109+ switch (type) {
110+ case klib::usb::descriptor::transfer_type::isochronous:
111+ return 0b01 ;
112+ case klib::usb::descriptor::transfer_type::bulk:
113+ return 0b10 ;
114+ case klib::usb::descriptor::transfer_type::interrupt:
115+ return 0b11 ;
116+ default :
117+ return 0b00 ;
118+ }
119+ }
120+
121+ /* *
122+ * @brief Convert a mode to the correct raw value for the usb hardware
123+ *
124+ * @param mode
125+ * @return uint8_t
126+ */
127+ constexpr static bool endpoint_mode_to_raw (const klib::usb::usb::endpoint_mode mode) {
128+ switch (mode) {
129+ case klib::usb::usb::endpoint_mode::out:
130+ return false ;
131+ case klib::usb::usb::endpoint_mode::in:
132+ case klib::usb::usb::endpoint_mode::control:
133+ case klib::usb::usb::endpoint_mode::disabled:
134+ default :
135+ return true ;
136+ }
137+ }
138+
139+ static void clear_endpoint_state (const uint8_t endpoint) {
140+ state[endpoint].is_busy = false ;
141+ state[endpoint].requested_size = 0 ;
142+ state[endpoint].transferred_size = 0 ;
143+ state[endpoint].callback = nullptr ;
144+ state[endpoint].data = nullptr ;
145+ }
146+
147+ /* *
148+ * @brief Reset the bus
149+ *
150+ */
151+ static void reset () {
152+ // reset the usb
153+ Usb::port->UDCC |= (0x1 << 7 );
154+
155+ // change the power mode to self powered
156+ Usb::port->UDCC |= 0x1 ;
157+
158+ // configure enpoint 0 endpoint size.
159+ Usb::port->EP0C = max_endpoint_size;
160+
161+ // enable all the interrupts
162+ Usb::port->UDCIE = 0x3f ;
163+
164+ // check if we need to call the reset callback
165+ if constexpr (has_bus_reset_callback) {
166+ // call the device bus reset
167+ device::template bus_reset<usb_type>();
168+ }
169+ }
170+
101171 public:
102172 /* *
103173 * @brief Interrupt handler for the usb driver
@@ -106,9 +176,22 @@ namespace klib::core::mb9bf560l::io {
106176 *
107177 */
108178 static void irq_handler () {
179+ // get the status and the mask
180+ const uint8_t status = Usb::port->UDCS ;
181+ const uint8_t mask = Usb::port->UDCIE ;
109182
110- }
183+ // create the masked status
184+ const uint32_t masked_status = status & mask;
185+
186+ // clear the interrupt status so we dont miss any
187+ // interrupts while the user code is running. We
188+ // clear a interrupt by setting it to zero. Invert
189+ // the mask to get this result
190+ Usb::port->UDCS = (~masked_status);
111191
192+
193+ }
194+
112195 public:
113196 /* *
114197 * @brief Initialize the usb hardware. This requires the usb pll to be enabled beforehand using
@@ -144,11 +227,26 @@ namespace klib::core::mb9bf560l::io {
144227 state[i].callback = nullptr ;
145228 }
146229
230+ // do a partial reset
231+ reset ();
232+
147233 // register ourselfs with the interrupt controller
148234 target::irq::register_irq<Usb::interrupt_id>(irq_handler);
149235
150236 // enable the usb interrupt
151237 target::enable_irq<Usb::interrupt_id>();
238+
239+ // clear the device addess
240+ set_device_address (0 );
241+
242+ // init the device
243+ device::template init<usb_type>();
244+
245+ // check if we should enable the usb connect feature
246+ if constexpr (UsbConnect) {
247+ // enable the usb connect pin to allow connections
248+ connect ();
249+ }
152250 }
153251
154252 /* *
@@ -211,7 +309,17 @@ namespace klib::core::mb9bf560l::io {
211309 const uint8_t endpoint, const klib::usb::usb::endpoint_mode mode,
212310 const klib::usb::descriptor::transfer_type type, const uint32_t size)
213311 {
214-
312+ // get the register we should write to (skip every other word)
313+ volatile uint16_t *const epc = ((volatile uint16_t *)&Usb::port->EP0C )[endpoint * 2 ];
314+
315+ // limit the size based on the endpoint number
316+ const uint16_t s = size & (endpoint == 0 ? 0x1ff : 0x7f );
317+
318+ // set the endpoint configuration
319+ epc = (
320+ s | (endpoint_mode_to_raw (mode) << 12 ) |
321+ (transfer_type_to_raw (type) << 13 )
322+ );
215323 }
216324
217325 /* *
@@ -269,7 +377,11 @@ namespace klib::core::mb9bf560l::io {
269377 * @param mode
270378 */
271379 static void stall (const uint8_t endpoint, const klib::usb::usb::endpoint_mode mode) {
380+ // get the register we should write to (skip every other word)
381+ volatile uint16_t *const epc = ((volatile uint16_t *)&Usb::port->EP0C )[endpoint * 2 ];
272382
383+ // set the stall bit
384+ (*epc) |= 0x1 << 9 ;
273385 }
274386
275387 /* *
@@ -279,7 +391,11 @@ namespace klib::core::mb9bf560l::io {
279391 * @param mode
280392 */
281393 static void un_stall (const uint8_t endpoint, const klib::usb::usb::endpoint_mode mode) {
394+ // get the register we should write to (skip every other word)
395+ volatile uint16_t *const epc = ((volatile uint16_t *)&Usb::port->EP0C )[endpoint * 2 ];
282396
397+ // clear the stall bit
398+ (*epc) = (*epc) & (~(0x1 << 9 ));
283399 }
284400
285401 /* *
@@ -291,7 +407,11 @@ namespace klib::core::mb9bf560l::io {
291407 * @return false
292408 */
293409 static bool is_stalled (const uint8_t endpoint, const klib::usb::usb::endpoint_mode mode) {
294- return true ;
410+ // get the register we should write to (skip every other word)
411+ volatile uint16_t *const epc = ((volatile uint16_t *)&Usb::port->EP0C )[endpoint * 2 ];
412+
413+ // return the endpoint stall bit
414+ return (*epc) & (0x1 << 9 );
295415 }
296416
297417 /* *
@@ -374,7 +494,20 @@ namespace klib::core::mb9bf560l::io {
374494 * @param mode
375495 */
376496 static void cancel (const uint8_t endpoint, const klib::usb::usb::endpoint_mode mode) {
497+ // get the callback
498+ const auto callback = state[endpoint].callback ;
499+
500+ // get the amount of data we have transferred
501+ const auto transferred = state[endpoint].transferred_size ;
377502
503+ // clear the state of the endpoint
504+ clear_endpoint_state (endpoint);
505+
506+ // check if the callback is valid
507+ if (callback) {
508+ // call the callback
509+ callback (endpoint, mode, klib::usb::usb::error::cancel, transferred);
510+ }
378511 }
379512 };
380513}
0 commit comments