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