Mbed OS Reference
Loading...
Searching...
No Matches
USBDevice.h
1/*
2 * Copyright (c) 2018-2019, Arm Limited and affiliates.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef USBDEVICE_H
19#define USBDEVICE_H
20
21#include <stddef.h>
22#include "USBDevice_Types.h"
23#include "USBPhy.h"
24#include "mbed_critical.h"
25#include "Callback.h"
26
27/**
28 * \defgroup drivers_USBDevice USBDevice class
29 * \ingroup drivers-internal-api-usb
30 * @{
31 */
32
33/**
34 * Core USB Device driver
35 *
36 * USB driver which wraps and provides synchronization for a USBPhy object.
37 */
38class USBDevice: public USBPhyEvents {
39public:
40 typedef void (USBDevice::*ep_cb_t)();
41
42 enum RequestResult {
43 Receive = 0,
44 Send = 1,
45 Success = 2,
46 Failure = 3,
47 PassThrough = 4,
48 };
49
50 enum DeviceState {
51 Attached,
52 Powered,
53 Default,
54 Address,
55 Configured
56 };
57
59 struct {
60 uint8_t dataTransferDirection;
61 uint8_t Type;
62 uint8_t Recipient;
63 } bmRequestType;
64 uint8_t bRequest;
65 uint16_t wValue;
66 uint16_t wIndex;
67 uint16_t wLength;
68 };
69
70 /**
71 * Instantiate a new USBDevice with the given parameters
72 *
73 * @param phy The USBPhy providing physical USB access
74 * @param vendor_id The USB vendor ID
75 * @param product_id The USB product ID
76 * @param product_release The device release number
77 */
78 USBDevice(USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
79
80 /**
81 * Cleanup this USBDevice
82 *
83 * This USBDevice must be uninitialized when the destructor is
84 * called or the behavior is undefined.
85 */
86 virtual ~USBDevice();
87
88 /**
89 * Initialize this instance
90 *
91 * This function must be called before calling
92 * any other functions of this class, unless specifically
93 */
94 void init();
95
96 /**
97 * Power down this instance
98 *
99 * Disable interrupts and stop sending events.
100 * This method can be used for temporary power-saving; This call can allow
101 * USB to be temporarily disabled to permit power saving.
102 * However, it is up to the user to make sure all the
103 * transfers have concluded (for example when USB power is lost).
104 * USBDevice::connect can be used to resume USB operation.
105 */
106 void deinit();
107
108 /**
109 * Check if the device is configured
110 *
111 * @returns true if configured, false otherwise
112 */
114
115 /**
116 * Connect a device
117 * This method can also be used to resume USB operation when USB power is
118 * detected after it was suspended via USBDevice::deinit.
119 */
120 void connect();
121
122 /**
123 * Disconnect a device
124 */
126
127 /**
128 * Enable the start of frame interrupt
129 *
130 * Call USBDevice::callback_sof on every frame.
131 */
133
134 /**
135 * Disable the start of frame interrupt
136 *
137 * Stop calling USBDevice::callback_sof.
138 */
140
141 /**
142 * Add an endpoint
143 *
144 * @param endpoint Endpoint to enable
145 * @param max_packet Maximum size of a packet which can be sent or received on this endpoint
146 * @param type Endpoint type - USB_EP_TYPE_BULK, USB_EP_TYPE_INT or USB_EP_TYPE_ISO
147 * @param callback Method pointer to be called when a packet is transferred
148 * @returns true if successful, false otherwise
149 */
150 bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, mbed::Callback<void()> callback = nullptr);
151
152 /**
153 * Add an endpoint
154 *
155 * @param endpoint Endpoint to enable
156 * @param max_packet Maximum size of a packet which can be sent or received on this endpoint
157 * @param type Endpoint type - USB_EP_TYPE_BULK, USB_EP_TYPE_INT or USB_EP_TYPE_ISO
158 * @param callback Method pointer to be called when a packet is transferred
159 * @returns true if successful, false otherwise
160 */
161 template<typename T>
162 bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, void (T::*callback)())
163 {
164 return endpoint_add(endpoint, max_packet, type, mbed::callback(this, static_cast<ep_cb_t>(callback)));
165 }
166
167 /**
168 * Remove an endpoint
169 *
170 * @param endpoint Endpoint to disable
171 * @note This endpoint must already have been setup with endpoint_add
172 */
173 void endpoint_remove(usb_ep_t endpoint);
174
175 /**
176 * Remove all non-zero endpoints
177 */
179
180 /**
181 * Stall an endpoint
182 *
183 * If there is an ongoing transfer on this endpoint then it will
184 * be aborted.
185 *
186 * @param endpoint Endpoint to stall
187 * @note You cannot stall endpoint 0 with this function
188 * @note This endpoint must already have been setup with endpoint_add
189 */
190 void endpoint_stall(usb_ep_t endpoint);
191
192 /**
193 * Un-stall an endpoint
194 *
195 * Un-stalling an endpoint resets data toggle back to DATA0.
196 * Additionally, if there is an ongoing transfer on this endpoint
197 * it will be aborted.
198 *
199 * @param endpoint Endpoint to un-stall
200 * @note This endpoint must already have been setup with endpoint_add
201 */
202 void endpoint_unstall(usb_ep_t endpoint);
203
204 /**
205 * Get the current maximum size for this endpoint
206 *
207 * Return the currently configured maximum packet size, wMaxPacketSize,
208 * for this endpoint.
209 * @note This endpoint must already have been setup with endpoint_add
210 */
211 uint32_t endpoint_max_packet_size(usb_ep_t endpoint);
212
213 /**
214 * Abort the current transfer on this endpoint
215 *
216 * @param endpoint endpoint with transfer to abort
217 * @note This endpoint must already have been setup with endpoint_add
218 */
219 void endpoint_abort(usb_ep_t endpoint);
220
221 /**
222 * start a read on the given endpoint
223 *
224 * Start a read on the given endpoint. The data buffer must remain
225 * unchanged until the transfer either completes or is aborted.
226 *
227 * @param endpoint endpoint to read data from
228 * @param buffer buffer to fill with read data
229 * @param size The size of data to read. This must be greater than or equal
230 * to the max packet size for this endpoint
231 * @return true if the read was completed, otherwise false
232 * @note This endpoint must already have been setup with endpoint_add
233 */
234 bool read_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size);
235
236 /**
237 * Get the status of a read
238 *
239 * @param endpoint endpoint to get the status of
240 * @return number of bytes read by this endpoint
241 */
242 uint32_t read_finish(usb_ep_t endpoint);
243
244 /**
245 * Write a data to the given endpoint
246 *
247 * Write data to an endpoint. The data sent must remain unchanged until
248 * the transfer either completes or is aborted.
249 *
250 * @param endpoint endpoint to write data to
251 * @param buffer data to write
252 * @param size the size of data to send. This must be less than or equal to the
253 * max packet size of this endpoint
254 * @note This endpoint must already have been setup with endpoint_add
255 */
256 bool write_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size);
257
258 /**
259 * Get the status of a write
260 *
261 * @param endpoint endpoint to get the status of
262 * @return number of bytes sent by this endpoint
263 */
264 uint32_t write_finish(usb_ep_t endpoint);
265
266 /*
267 * Get device descriptor.
268 *
269 * @returns pointer to the device descriptor
270 */
271 virtual const uint8_t *device_desc();
272
273 /*
274 * Get configuration descriptor
275 *
276 * @param index descriptor index
277 * @returns pointer to the configuration descriptor
278 */
279 virtual const uint8_t *configuration_desc(uint8_t index) = 0;
280
281 /*
282 * Get string lang id descriptor
283 *
284 * @return pointer to the string lang id descriptor
285 */
286 virtual const uint8_t *string_langid_desc();
287
288 /*
289 * Get string manufacturer descriptor
290 *
291 * @returns pointer to the string manufacturer descriptor
292 */
293 virtual const uint8_t *string_imanufacturer_desc();
294
295 /*
296 * Get string product descriptor
297 *
298 * @returns pointer to the string product descriptor
299 */
300 virtual const uint8_t *string_iproduct_desc();
301
302 /*
303 * Get string serial descriptor
304 *
305 * @returns pointer to the string serial descriptor
306 */
307 virtual const uint8_t *string_iserial_desc();
308
309 /*
310 * Get string configuration descriptor
311 *
312 * @returns pointer to the string configuration descriptor
313 */
314 virtual const uint8_t *string_iconfiguration_desc();
315
316 /*
317 * Get string interface descriptor
318 *
319 * @returns pointer to the string interface descriptor
320 */
321 virtual const uint8_t *string_iinterface_desc();
322
323 /*
324 * Get the length of the report descriptor
325 *
326 * @returns length of the report descriptor
327 */
328 virtual uint16_t report_desc_dength()
329 {
330 return 0;
331 };
332
333protected:
334
335 /**
336 * Called by USBDevice layer on power state change.
337 *
338 * @param powered true if device is powered, false otherwise
339 *
340 * Warning: Called in ISR context
341 */
342 virtual void callback_power(bool powered)
343 {
344
345 }
346
347 /**
348 * Called by USBDevice layer on each new USB frame.
349 *
350 * Callbacks are enabled and disabled by calling sof_enable
351 * and sof_disable.
352 *
353 * @param frame_number The current frame number
354 *
355 * Warning: Called in ISR context
356 */
357 virtual void callback_sof(int frame_number)
358 {
359
360 }
361
362 /**
363 * Called by USBDevice layer on bus reset.
364 *
365 * complete_reset must be called after
366 * the device is fully reset.
367 *
368 * Warning: Called in ISR context
369 */
370 virtual void callback_reset()
371 {
372
373 }
374
375 /**
376 * Called when USB changes state
377 *
378 * @param new_state The new state of the USBDevice
379 *
380 * Warning: Called in ISR context
381 */
382 virtual void callback_state_change(DeviceState new_state) = 0;
383
384 /**
385 * Called by USBDevice on Endpoint0 request.
386 *
387 * This is used to handle extensions to standard requests
388 * and class specific requests. The function complete_request
389 * must be always be called in response to this callback.
390 *
391 * Warning: Called in ISR context
392 */
393 virtual void callback_request(const setup_packet_t *setup) = 0;
394
395 /**
396 * Called to complete the setup stage of a callback request
397 *
398 * Possible options that can be passed as a result are:
399 * - Receive - Start the data OUT phase of this control transfer
400 * - Send - Start the data IN phase of this control transfer
401 * - Success - Operation was a success so start the status phase
402 * - Failure - Operation failed or is unsupported so send a stall
403 * - PassThrough - Pass on the request for standard processing
404 *
405 * @param result The result of the setup phase.
406 * @param data Buffer to send or receive if the result is Send or Receive
407 * @param size Size to transfer if the result is Send or Receive
408 */
409 void complete_request(RequestResult result, uint8_t *data = NULL, uint32_t size = 0);
410
411 /**
412 * Called by USBDevice on data stage completion
413 *
414 * The function complete_request_xfer_done must be always be called
415 * in response to this callback.
416 *
417 * @param setup Setup packet of the current request
418 * @param aborted false if the operation was aborted, true otherwise
419 *
420 * Warning: Called in ISR context
421 */
422 virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted) = 0;
423
424 /**
425 * Called to complete the data stage of a callback request
426 *
427 * @param success true if the operation was successful, false otherwise
428 */
429 void complete_request_xfer_done(bool success);
430
431 /*
432 * Called by USBDevice layer in response to set_configuration.
433 *
434 * Upon reception of this command endpoints of the previous configuration
435 * if any must be removed with endpoint_remove and new endpoint added with
436 * endpoint_add.
437 *
438 * @param configuration Number of the configuration
439 *
440 * Warning: Called in ISR context
441 */
442 virtual void callback_set_configuration(uint8_t configuration) = 0;
443
444 /**
445 * Called to complete a set configuration command
446 *
447 * @param success true if the configuration was set, false otherwise
448 */
449 void complete_set_configuration(bool success);
450
451 /*
452 * Called by USBDevice layer in response to set_interface.
453 *
454 * Upon reception of this command endpoints of any previous interface
455 * if any must be removed with endpoint_remove and new endpoint added with
456 * endpoint_add.
457 *
458 * @param configuration Number of the configuration
459 *
460 * Warning: Called in ISR context
461 */
462 virtual void callback_set_interface(uint16_t interface, uint8_t alternate) = 0;
463
464 /**
465 * Called to complete a set interface command
466 *
467 * @param success true if the interface was set, false otherwise
468 */
469 void complete_set_interface(bool success);
470
471 /**
472 * Find a descriptor type inside the configuration descriptor
473 *
474 * @param descriptor_type Type of descriptor to find
475 * @param index Configuration descriptor index ( 0 if only one configuration present )
476 * @return A descriptor of the given type or NULL if none were found
477 */
478 uint8_t *find_descriptor(uint8_t descriptor_type, uint8_t index = 0);
479
480 /**
481 * Get the endpoint table of this device
482 *
483 * @return Endpoint table of the USBPhy attached to this USBDevice
484 */
486
487 /**
488 * Callback called to indicate the USB processing needs to be done
489 */
490 virtual void start_process();
491
492 /**
493 * Acquire exclusive access to this instance USBDevice
494 */
495 virtual void lock();
496
497 /**
498 * Release exclusive access to this instance USBDevice
499 */
500 virtual void unlock();
501
502 /**
503 * Assert that the current thread of execution holds the lock
504 *
505 */
506 virtual void assert_locked();
507
508 uint16_t vendor_id;
509 uint16_t product_id;
510 uint16_t product_release;
511 uint8_t device_descriptor[18];
512
513private:
514 // USBPhyEvents
515 virtual void power(bool powered);
516 virtual void suspend(bool suspended);
517 virtual void sof(int frame_number);
518 virtual void reset();
519 virtual void ep0_setup();
520 virtual void ep0_out();
521 virtual void ep0_in();
522 virtual void out(usb_ep_t endpoint);
523 virtual void in(usb_ep_t endpoint);
524
525 bool _request_get_descriptor();
526 bool _control_out();
527 bool _control_in();
528 bool _request_set_address();
529 bool _request_set_configuration();
530 bool _request_set_feature();
531 bool _request_clear_feature();
532 bool _request_get_status();
533 bool _request_setup();
534 void _control_setup();
535 void _control_abort();
536 void _control_abort_start();
537 void _control_setup_continue();
538 void _decode_setup_packet(uint8_t *data, setup_packet_t *packet);
539 bool _request_get_configuration();
540 bool _request_get_interface();
541 bool _request_set_interface();
542 void _change_state(DeviceState state);
543 void _run_later(void (USBDevice::*function)());
544
545 void _complete_request();
546 void _complete_request_xfer_done();
547 void _complete_set_configuration();
548 void _complete_set_interface();
549
550 void _clear_endpoints();
551
552 struct endpoint_info_t {
553 mbed::Callback<void()> callback;
554 uint16_t max_packet_size;
555 uint16_t transfer_size;
556 uint8_t flags;
557 uint8_t pending;
558 };
559
560 struct usb_device_t {
561 volatile DeviceState state;
562 uint8_t configuration;
563 bool suspended;
564 };
565
566 enum ControlState {
567 Setup,
568 DataOut,
569 DataIn,
570 Status
571 };
572
573 enum UserCallback {
574 None,
575 Request,
576 RequestXferDone,
577 SetConfiguration,
578 SetInterface
579 };
580
581 struct complete_request_t {
582 RequestResult result;
583 uint8_t *data;
584 uint32_t size;
585 };
586
587 union complete_args_t {
588 complete_request_t request;
589 bool status;
590 };
591
592 struct control_transfer_t {
593 setup_packet_t setup;
594 uint8_t *ptr;
595 uint32_t remaining;
596 uint8_t direction;
597 bool zlp;
598 bool notify;
599 ControlState stage;
600 UserCallback user_callback;
601 complete_args_t args;
602 };
603
604 endpoint_info_t _endpoint_info[32 - 2];
605
606 USBPhy *_phy;
607 bool _initialized;
608 bool _connected;
609 bool _endpoint_add_remove_allowed;
610 control_transfer_t _transfer;
611 usb_device_t _device;
612 uint32_t _max_packet_size_ep0;
613 void (USBDevice::*_post_process)();
614
615 bool _setup_ready;
616 bool _abort_control;
617
618 uint16_t _current_interface;
619 uint8_t _current_alternate;
620 uint32_t _locked;
621};
622
623/** @}*/
624
625#endif
Core USB Device driver.
Definition: USBDevice.h:38
bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, void(T::*callback)())
Add an endpoint.
Definition: USBDevice.h:162
void init()
Initialize this instance.
bool write_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size)
Write a data to the given endpoint.
uint8_t * find_descriptor(uint8_t descriptor_type, uint8_t index=0)
Find a descriptor type inside the configuration descriptor.
uint32_t endpoint_max_packet_size(usb_ep_t endpoint)
Get the current maximum size for this endpoint.
void connect()
Connect a device This method can also be used to resume USB operation when USB power is detected afte...
virtual void callback_power(bool powered)
Called by USBDevice layer on power state change.
Definition: USBDevice.h:342
uint32_t write_finish(usb_ep_t endpoint)
Get the status of a write.
virtual void callback_reset()
Called by USBDevice layer on bus reset.
Definition: USBDevice.h:370
void complete_set_configuration(bool success)
Called to complete a set configuration command.
void sof_enable()
Enable the start of frame interrupt.
virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted)=0
Called by USBDevice on data stage completion.
bool read_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size)
start a read on the given endpoint
bool configured()
Check if the device is configured.
uint32_t read_finish(usb_ep_t endpoint)
Get the status of a read.
USBDevice(USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
Instantiate a new USBDevice with the given parameters.
void endpoint_remove(usb_ep_t endpoint)
Remove an endpoint.
void complete_request_xfer_done(bool success)
Called to complete the data stage of a callback request.
virtual void callback_request(const setup_packet_t *setup)=0
Called by USBDevice on Endpoint0 request.
const usb_ep_table_t * endpoint_table()
Get the endpoint table of this device.
void disconnect()
Disconnect a device.
void deinit()
Power down this instance.
virtual void callback_sof(int frame_number)
Called by USBDevice layer on each new USB frame.
Definition: USBDevice.h:357
void complete_set_interface(bool success)
Called to complete a set interface command.
virtual void callback_state_change(DeviceState new_state)=0
Called when USB changes state.
void endpoint_abort(usb_ep_t endpoint)
Abort the current transfer on this endpoint.
virtual ~USBDevice()
Cleanup this USBDevice.
void endpoint_unstall(usb_ep_t endpoint)
Un-stall an endpoint.
void endpoint_stall(usb_ep_t endpoint)
Stall an endpoint.
virtual void start_process()
Callback called to indicate the USB processing needs to be done.
bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, mbed::Callback< void()> callback=nullptr)
Add an endpoint.
virtual void lock()
Acquire exclusive access to this instance USBDevice.
virtual void unlock()
Release exclusive access to this instance USBDevice.
virtual void assert_locked()
Assert that the current thread of execution holds the lock.
void complete_request(RequestResult result, uint8_t *data=NULL, uint32_t size=0)
Called to complete the setup stage of a callback request.
void sof_disable()
Disable the start of frame interrupt.
void endpoint_remove_all()
Remove all non-zero endpoints.
Event handler for USBPhy.
Definition: USBPhyEvents.h:31
Abstract interface to physical USB hardware.
Definition: USBPhy.h:82
Callback class based on template specialization.
Definition: Callback.h:53
Callback< R(ArgTs...)> callback(R(*func)(ArgTs...)=nullptr) noexcept
Create a callback class with type inferred from the arguments.
Definition: Callback.h:678