1 // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 #include <stdint.h>
22 #include "freertos/FreeRTOS.h"
23 #include "freertos/ringbuf.h"
24 #include "freertos/semphr.h"
25 #include "freertos/timers.h"
26 #include "tusb.h"
27 #include "tinyusb.h"
28 
29 /**
30  * @brief CDC ports available to setup
31  */
32 typedef enum{
33     TINYUSB_CDC_ACM_0 = 0x0
34 }tinyusb_cdcacm_itf_t;
35 
36 /* Callbacks and events
37    ********************************************************************* */
38 
39 /**
40  * @brief Data provided to the input of the `callback_rx_wanted_char` callback
41  */
42 typedef struct {
43     char wanted_char; /*!< Wanted character */
44 } cdcacm_event_rx_wanted_char_data_t;
45 
46 /**
47  * @brief Data provided to the input of the `callback_line_state_changed` callback
48  */
49 typedef struct {
50     bool dtr; /*!< Data Terminal Ready (DTR) line state */
51     bool rts; /*!< Request To Send (RTS) line state */
52 } cdcacm_event_line_state_changed_data_t;
53 
54 /**
55  * @brief Data provided to the input of the `line_coding_changed` callback
56  */
57 typedef struct {
58     cdc_line_coding_t const *p_line_coding; /*!< New line coding value */
59 } cdcacm_event_line_coding_changed_data_t;
60 
61 /**
62  * @brief Types of CDC ACM events
63  */
64 typedef enum {
65     CDC_EVENT_RX,
66     CDC_EVENT_RX_WANTED_CHAR,
67     CDC_EVENT_LINE_STATE_CHANGED,
68     CDC_EVENT_LINE_CODING_CHANGED
69 } cdcacm_event_type_t;
70 
71 /**
72  * @brief Describes an event passing to the input of a callbacks
73  */
74 typedef struct {
75     cdcacm_event_type_t type; /*!< Event type */
76     union {
77         cdcacm_event_rx_wanted_char_data_t rx_wanted_char_data; /*!< Data input of the `callback_rx_wanted_char` callback */
78         cdcacm_event_line_state_changed_data_t line_state_changed_data; /*!< Data input of the `callback_line_state_changed` callback */
79         cdcacm_event_line_coding_changed_data_t line_coding_changed_data; /*!< Data input of the `line_coding_changed` callback */
80     };
81 } cdcacm_event_t;
82 
83 /**
84  * @brief CDC-ACM callback type
85  */
86 typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event);
87 
88 /*********************************************************************** Callbacks and events*/
89 /* Other structs
90    ********************************************************************* */
91 
92 /**
93  * @brief Configuration structure for CDC-ACM
94  */
95 typedef struct {
96     tinyusb_usbdev_t usb_dev; /*!< Usb device to set up */
97     tinyusb_cdcacm_itf_t cdc_port;  /*!< CDC port */
98     size_t rx_unread_buf_sz; /*!< Amount of data that can be passed to the AMC at once */
99     tusb_cdcacm_callback_t callback_rx;  /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
100     tusb_cdcacm_callback_t callback_rx_wanted_char; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
101     tusb_cdcacm_callback_t callback_line_state_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
102     tusb_cdcacm_callback_t callback_line_coding_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
103 } tinyusb_config_cdcacm_t;
104 
105 /*********************************************************************** Other structs*/
106 /* Public functions
107    ********************************************************************* */
108 /**
109  * @brief Initialize CDC ACM. Initialization will be finished with
110  *          the `tud_cdc_line_state_cb` callback
111  *
112  * @param cfg - init configuration structure
113  * @return esp_err_t
114  */
115 esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg);
116 
117 
118 /**
119  * @brief Register a callback invoking on CDC event. If the callback had been
120  *        already registered, it will be overwritten
121  *
122  * @param itf - number of a CDC object
123  * @param event_type - type of registered event for a callback
124  * @param callback  - callback function
125  * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
126  */
127 esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf,
128         cdcacm_event_type_t event_type,
129         tusb_cdcacm_callback_t callback);
130 
131 
132 /**
133  * @brief Unregister a callback invoking on CDC event.
134  *
135  * @param itf - number of a CDC object
136  * @param event_type - type of registered event for a callback
137  * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
138  */
139 esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type);
140 
141 
142 /**
143  * @brief Sent one character to a write buffer
144  *
145  * @param itf - number of a CDC object
146  * @param ch - character to send
147  * @return size_t - amount of queued bytes
148  */
149 size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch);
150 
151 
152 /**
153  * @brief Write data to write buffer from a byte array
154  *
155  * @param itf - number of a CDC object
156  * @param in_buf - a source array
157  * @param in_size - size to write from arr_src
158  * @return size_t - amount of queued bytes
159  */
160 size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size);
161 
162 /**
163  * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer.
164  *
165  *        WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush
166  *        after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until
167  *        ont of the next callbacks ends.
168  *        SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT
169  *
170  * @param itf - number of a CDC object
171  * @param timeout_ticks - waiting until flush will be considered as failed
172  * @return esp_err_t -  ESP_OK if (timeout_ticks > 0) and and flush was successful,
173  *                      ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0)
174  *                      ESP_FAIL if flush was unsuccessful
175  */
176 esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks);
177 
178 /**
179  * @brief Read a content to the array, and defines it's size to the sz_store
180  *
181  * @param itf - number of a CDC object
182  * @param out_buf - to this array will be stored the object from a CDC buffer
183  * @param out_buf_sz - size of buffer for results
184  * @param rx_data_size - to this address will be stored the object's size
185  * @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE
186  */
187 esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size);
188 
189 
190 /**
191  * @brief Check if the ACM initialized
192  *
193  * @param itf - number of a CDC object
194  * @return true or false
195  */
196 bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf);
197 
198 /*********************************************************************** Public functions*/
199 
200 #ifdef __cplusplus
201 }
202 #endif
203