Mistake on this page?
Report an issue in GitHub or email us
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  */
38 class USBDevice: public USBPhyEvents {
39 public:
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 
58  struct setup_packet_t {
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  */
113  bool configured();
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  */
125  void disconnect();
126 
127  /**
128  * Enable the start of frame interrupt
129  *
130  * Call USBDevice::callback_sof on every frame.
131  */
132  void sof_enable();
133 
134  /**
135  * Disable the start of frame interrupt
136  *
137  * Stop calling USBDevice::callback_sof.
138  */
139  void sof_disable();
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  */
178  void endpoint_remove_all();
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 
333 protected:
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 
513 private:
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  struct endpoint_info_t {
552  uint16_t max_packet_size;
553  uint16_t transfer_size;
554  uint8_t flags;
555  uint8_t pending;
556  };
557 
558  struct usb_device_t {
559  volatile DeviceState state;
560  uint8_t configuration;
561  bool suspended;
562  };
563 
564  enum ControlState {
565  Setup,
566  DataOut,
567  DataIn,
568  Status
569  };
570 
571  enum UserCallback {
572  None,
573  Request,
574  RequestXferDone,
575  SetConfiguration,
576  SetInterface
577  };
578 
579  struct complete_request_t {
580  RequestResult result;
581  uint8_t *data;
582  uint32_t size;
583  };
584 
585  union complete_args_t {
586  complete_request_t request;
587  bool status;
588  };
589 
590  struct control_transfer_t {
591  setup_packet_t setup;
592  uint8_t *ptr;
593  uint32_t remaining;
594  uint8_t direction;
595  bool zlp;
596  bool notify;
597  ControlState stage;
598  UserCallback user_callback;
599  complete_args_t args;
600  };
601 
602  endpoint_info_t _endpoint_info[32 - 2];
603 
604  USBPhy *_phy;
605  bool _initialized;
606  bool _connected;
607  bool _endpoint_add_remove_allowed;
608  control_transfer_t _transfer;
609  usb_device_t _device;
610  uint32_t _max_packet_size_ep0;
611  void (USBDevice::*_post_process)();
612 
613  bool _setup_ready;
614  bool _abort_control;
615 
616  uint16_t _current_interface;
617  uint8_t _current_alternate;
618  uint32_t _locked;
619 };
620 
621 /** @}*/
622 
623 #endif
void complete_request(RequestResult result, uint8_t *data=NULL, uint32_t size=0)
Called to complete the setup stage of a callback request.
bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, mbed::Callback< void()> callback=nullptr)
Add an endpoint.
void sof_enable()
Enable the start of frame interrupt.
void endpoint_remove_all()
Remove all non-zero endpoints.
void deinit()
Power down this instance.
void complete_request_xfer_done(bool success)
Called to complete the data stage of a callback request.
void endpoint_stall(usb_ep_t endpoint)
Stall an endpoint.
void disconnect()
Disconnect a device.
void endpoint_remove(usb_ep_t endpoint)
Remove an endpoint.
uint32_t read_finish(usb_ep_t endpoint)
Get the status of a read.
virtual void callback_power(bool powered)
Called by USBDevice layer on power state change.
Definition: USBDevice.h:342
uint8_t * find_descriptor(uint8_t descriptor_type, uint8_t index=0)
Find a descriptor type inside the configuration descriptor.
virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted)=0
Called by USBDevice on data stage completion.
void connect()
Connect a device This method can also be used to resume USB operation when USB power is detected afte...
Callback< R(ArgTs...)> callback(R(*func)(ArgTs...)=nullptr) noexcept
Create a callback class with type inferred from the arguments.
Definition: Callback.h:678
Abstract interface to physical USB hardware.
Definition: USBPhy.h:82
virtual void callback_reset()
Called by USBDevice layer on bus reset.
Definition: USBDevice.h:370
void endpoint_unstall(usb_ep_t endpoint)
Un-stall an endpoint.
void complete_set_configuration(bool success)
Called to complete a set configuration command.
virtual void callback_request(const setup_packet_t *setup)=0
Called by USBDevice on Endpoint0 request.
virtual void callback_state_change(DeviceState new_state)=0
Called when USB changes state.
bool read_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size)
start a read on the given endpoint
void sof_disable()
Disable the start of frame interrupt.
virtual void lock()
Acquire exclusive access to this instance USBDevice.
Core USB Device driver.
Definition: USBDevice.h:38
const usb_ep_table_t * endpoint_table()
Get the endpoint table of this device.
virtual void start_process()
Callback called to indicate the USB processing needs to be done.
uint32_t endpoint_max_packet_size(usb_ep_t endpoint)
Get the current maximum size for this endpoint.
virtual void unlock()
Release exclusive access to this instance USBDevice.
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.
virtual ~USBDevice()
Cleanup this USBDevice.
void endpoint_abort(usb_ep_t endpoint)
Abort the current transfer on this endpoint.
USBDevice(USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
Instantiate a new USBDevice with the given parameters.
bool configured()
Check if the device is configured.
Callback class based on template specialization.
Definition: Callback.h:53
void complete_set_interface(bool success)
Called to complete a set interface command.
virtual void callback_sof(int frame_number)
Called by USBDevice layer on each new USB frame.
Definition: USBDevice.h:357
Event handler for USBPhy.
Definition: USBPhyEvents.h:31
virtual void assert_locked()
Assert that the current thread of execution holds the lock.
uint32_t write_finish(usb_ep_t endpoint)
Get the status of a write.
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
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.