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