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 #include <stdint.h>
16 #include "esp_check.h"
17 #include "esp_err.h"
18 #include "esp_log.h"
19 #include "tusb.h"
20 #include "cdc.h"
21 #include "sdkconfig.h"
22
23 static const char *TAG = "tusb_cdc";
24
25 #define CDC_INTF_NUM CFG_TUD_CDC // number of cdc blocks
26
27 static esp_tusb_cdc_t *cdc_obj[CDC_INTF_NUM] = {};
28
29 /* Common CDC functions
30 ********************************************************************* */
tinyusb_cdc_initialized(int itf)31 bool tinyusb_cdc_initialized(int itf)
32 {
33 return (cdc_obj[itf] != NULL);
34 }
35
cdc_interface_check(int itf)36 static esp_err_t cdc_interface_check(int itf)
37 {
38 if (tinyusb_cdc_initialized(itf)) {
39 return ESP_OK;
40 } else {
41 ESP_LOGE(TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
42 return ESP_ERR_INVALID_STATE;
43 }
44 }
45
46 /**
47 * @brief
48 *
49 * @param itf
50 * @param expected_inited
51 * @param expected_type use -1 if you don't care
52 * @return esp_err_t
53 */
cdc_obj_check(int itf,bool expected_inited,tusb_class_code_t expected_type)54 static esp_err_t cdc_obj_check(int itf, bool expected_inited, tusb_class_code_t expected_type)
55 {
56 bool inited = (cdc_obj[itf] != NULL);
57 if (expected_inited != inited) {
58 ESP_LOGE(TAG, "Wrong state of the interface. Expected state: %s",
59 expected_inited ? "initialized" : "not initialized");
60 return ESP_ERR_INVALID_STATE;
61 }
62 if (inited && (expected_type != -1) && !(cdc_obj[itf]->type == expected_type)) {
63 ESP_LOGE(TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type);
64 return ESP_ERR_INVALID_ARG;
65 }
66 return ESP_OK;
67 }
68
tinyusb_cdc_get_intf(int itf_num)69 esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num)
70 {
71 if (cdc_interface_check(itf_num) != ESP_OK) {
72 return NULL;
73 }
74 return cdc_obj[itf_num];
75 }
76
77 /*********************************************************************** Common CDC functions*/
78 /* CDC class funcs
79 ********************************************************************* */
tusb_cdc_comm_init(int itf)80 static esp_err_t tusb_cdc_comm_init(int itf)
81 {
82 ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed");
83 cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t));
84 if (cdc_obj[itf] != NULL) {
85 cdc_obj[itf]->type = TUSB_CLASS_CDC;
86 ESP_LOGD(TAG, "CDC Comm class initialized");
87 return ESP_OK;
88 } else {
89 ESP_LOGE(TAG, "CDC Comm initialization error");
90 return ESP_FAIL;
91 }
92 }
93
tusb_cdc_deinit_comm(int itf)94 static esp_err_t tusb_cdc_deinit_comm(int itf)
95 {
96 ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC), TAG, "cdc_obj_check failed");
97 free(cdc_obj[itf]);
98 cdc_obj[itf] = NULL;
99 return ESP_OK;
100 }
101
tusb_cdc_data_init(int itf)102 static esp_err_t tusb_cdc_data_init(int itf)
103 {
104 ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed");
105 cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t));
106 if (cdc_obj[itf] != NULL) {
107 cdc_obj[itf]->type = TUSB_CLASS_CDC_DATA;
108 ESP_LOGD(TAG, "CDC Data class initialized");
109 return ESP_OK;
110 } else {
111 ESP_LOGE(TAG, "CDC Data initialization error");
112 return ESP_FAIL;
113 }
114 }
115
tusb_cdc_deinit_data(int itf)116 static esp_err_t tusb_cdc_deinit_data(int itf)
117 {
118 ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed");
119 free(cdc_obj[itf]);
120 cdc_obj[itf] = NULL;
121 return ESP_OK;
122 }
123 /*********************************************************************** CDC class funcs*/
124 /* CDC initialization
125 ********************************************************************* */
tinyusb_cdc_init(int itf,const tinyusb_config_cdc_t * cfg)126 esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg)
127 {
128 ESP_LOGD(TAG, "CDC initialization...");
129 if (itf != 0) {
130 ESP_LOGE(TAG, "There is not CDC no.%d", itf);
131 return ESP_ERR_INVALID_ARG;
132 }
133 if (cfg->cdc_class == TUSB_CLASS_CDC) {
134 ESP_RETURN_ON_ERROR(tusb_cdc_comm_init(itf), TAG, "tusb_cdc_comm_init failed");
135 cdc_obj[itf]->cdc_subclass.comm_subclass = cfg->cdc_subclass.comm_subclass;
136 } else {
137 ESP_RETURN_ON_ERROR(tusb_cdc_data_init(itf), TAG, "tusb_cdc_data_init failed");
138 cdc_obj[itf]->cdc_subclass.data_subclass = cfg->cdc_subclass.data_subclass;
139 }
140 cdc_obj[itf]->usb_dev = cfg->usb_dev;
141 return ESP_OK;
142 }
143
144
tinyusb_cdc_deinit(int itf)145 esp_err_t tinyusb_cdc_deinit(int itf)
146 {
147 if (itf != 0) {
148 ESP_LOGE(TAG, "There is not CDC no.%d", itf);
149 return ESP_ERR_INVALID_ARG;
150 }
151 if (cdc_obj[itf]->type == TUSB_CLASS_CDC) {
152 ESP_RETURN_ON_ERROR(tusb_cdc_deinit_comm(itf), TAG, "tusb_cdc_deinit_comm failed");
153 } else if (cdc_obj[itf]->type == TUSB_CLASS_CDC_DATA) {
154 ESP_RETURN_ON_ERROR(tusb_cdc_deinit_data(itf), TAG, "tusb_cdc_deinit_data failed");
155 } else {
156 return ESP_ERR_INVALID_ARG;
157 }
158 ESP_LOGD(TAG, "De-initialized");
159 return ESP_OK;
160 }
161 /*********************************************************************** CDC initialization*/
162