1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/** 14 * @brief USB CDC ACM driver 15 * @see USB CDC specification and CDC PSTN subclass specification 16 */ 17#include <stdio.h> 18#include <string.h> 19 20#include <utils/circular_buffer.h> 21#include <platsupport/sync/atomic.h> 22#include "../services.h" 23#include "cdc.h" 24 25/* 26 * XXX: In theory the maximum xact size can be up to 20K, however, our DMA 27 * allocator cannot handle that large allocation at the moment. 28 */ 29#define CDC_READ_XACT_SIZE 128 30#define CDC_READ_BUFFER_SIZE 4096 31 32static const char *subclass_codes[] = { 33 "Reserved", 34 "Direct Line Control Model", 35 "Abstract Control Model", 36 "Telephone Control Model", 37 "Multi-Channel Control Model", 38 "CAPI Control Model", 39 "Ethernet Networking Control Model", 40 "ATM Networking Control Model", 41 "Wireless Handset Control Model", 42 "Device Management", 43 "Mobile Direct Line Model", 44 "OBEX", 45 "Ethernet Emulation Mode", 46 "Mobile Broadband Interface Model" 47}; 48 49static const char *func_subtype_codes[] = { 50 "Header Functional", 51 "Call Management Functional", 52 "Abstract Control Management Functional", 53 "Direct Line Management Functional", 54 "Telephone Ringer Functional", 55 "Telephone Call and Line State Reporting Capabilities Functional", 56 "Union Functional", 57 "Country Selection Functional", 58 "Telephone Operational Modes Functional", 59 "USB Terminal Functional", 60 "Network Channel Terminal", 61 "Protocol Unit Functional", 62 "Extension Unit Functional", 63 "Multi-Channel Management Functional", 64 "CAPI Control Management Functional", 65 "Ethernet Networking Functional", 66 "ATM Networking Functional", 67 "Wireless Handset Control Model Functional", 68 "Mobile Direct Line Model Functional", 69 "MDLM Detail Functional", 70 "Device Management Model Functional", 71 "OBEX Functional", 72 "Command Set Functional", 73 "Command Set Detail Functional", 74 "Telephone Control Model Functional", 75 "OBEX Service Identifier Functional", 76 "NCM Functional", 77 "MBIM Functional", 78 "MBIM Extended Functional", 79 "RESERVED (future use)", 80 "RESERVED (vendor specific)" 81}; 82 83/* CDC device interface class */ 84enum usb_cdc_inf_class { 85 INF_COMM = 0x2, //Communication Interface Class 86 INF_DATA = 0xA //Data Interface Class 87}; 88 89/* USB Communication Device */ 90struct usb_cdc_device { 91 struct usb_dev *udev; //The handle to the underlying USB device 92 uint8_t subclass; //Subclass code 93 uint8_t config; //Active configuration 94 uint8_t comm; //Communication interface index 95 uint8_t data; //Data interface index 96 struct endpoint *ep_int; //Interrupt endpoint 97 struct endpoint *ep_in; //BULK in endpoint 98 struct endpoint *ep_out; //BULK out endpoint 99 struct xact read_xact; //Current read request 100 circ_buf_t read_buf; //Read buffer 101 int read_in_progress; 102}; 103 104static int 105usb_cdc_config_cb(void *token, int cfg, int iface, struct anon_desc *desc) 106{ 107 struct usb_cdc_device *cdc; 108 struct config_desc *cdesc; 109 struct iface_desc *idesc; 110 struct func_desc *fdesc; 111 112 if (!desc) { 113 return 0; 114 } 115 116 cdc = (struct usb_cdc_device *)token; 117 118 switch (desc->bDescriptorType) { 119 case CONFIGURATION: 120 cdesc = (struct config_desc*)desc; 121 cdc->config = cdesc->bConfigurationValue; 122 break; 123 case INTERFACE: 124 idesc = (struct iface_desc *)desc; 125 cdc->udev->class = idesc->bInterfaceClass; 126 cdc->subclass = idesc->bInterfaceSubClass; 127 if (cdc->udev->class == INF_COMM && cdc->subclass < 0xd) { 128 cdc->comm = idesc->bInterfaceNumber; 129 ZF_LOGD("Communication Interface\n"); 130 if (cdc->subclass < 0xd) { 131 ZF_LOGD(" |-- %s\n", subclass_codes[cdc->subclass]); 132 } 133 } else if (cdc->udev->class == INF_DATA) { 134 cdc->data = idesc->bInterfaceNumber; 135 ZF_LOGD("Data Interface\n"); 136 } 137 break; 138 case CS_INTERFACE: 139 fdesc = (struct func_desc *)desc; 140 if (fdesc->bDescriptorSubtype < 0x1d) { 141 ZF_LOGD(" %s\n", 142 func_subtype_codes[fdesc->bDescriptorSubtype]); 143 } else { 144 ZF_LOGD(" Function type reserved(%x)\n", 145 fdesc->bDescriptorSubtype); 146 } 147 break; 148 default: 149 break; 150 } 151 152 return 0; 153} 154 155static int usb_cdc_read_cb(void *token, enum usb_xact_status stat, int rbytes) 156{ 157 struct usb_dev *udev; 158 struct usb_cdc_device *cdc; 159 char *buf; 160 161 udev = (struct usb_dev*)token; 162 cdc = (struct usb_cdc_device*)udev->dev_data; 163 164 if (stat == XACTSTAT_SUCCESS) { 165 buf = (char*)xact_get_vaddr(&cdc->read_xact); 166 for (int i = 0; i < CDC_READ_XACT_SIZE - rbytes; i++) { 167 if (!circ_buf_is_full(&cdc->read_buf)) { 168 circ_buf_put(&cdc->read_buf, buf[i]); 169 } else { 170 break; 171 } 172 } 173 } 174 175 sync_atomic_decrement(&cdc->read_in_progress, __ATOMIC_RELAXED); 176 177 return 0; 178} 179 180int usb_cdc_bind(usb_dev_t *udev) 181{ 182 int err; 183 struct usb_cdc_device *cdc; 184 struct xact xact; 185 struct usbreq *req; 186 int class; 187 188 if (!udev) { 189 ZF_LOGF("Invalid device\n"); 190 } 191 192 cdc = usb_malloc(sizeof(struct usb_cdc_device)); 193 if (!cdc) { 194 ZF_LOGD("Not enough memory!\n"); 195 return -1; 196 } 197 198 cdc->udev = udev; 199 udev->dev_data = (struct udev_priv*)cdc; 200 201 /* Parse the descriptors */ 202 err = usbdev_parse_config(udev, usb_cdc_config_cb, cdc); 203 if (err) { 204 ZF_LOGF("Invalid descriptors\n"); 205 } 206 207 /* Find endpoints */ 208 for (int i = 0; udev->ep[i] != NULL; i++) { 209 if (udev->ep[i]->type == EP_BULK) { 210 if (udev->ep[i]->dir == EP_DIR_OUT) { 211 cdc->ep_out = udev->ep[i]; 212 } else { 213 cdc->ep_in = udev->ep[i]; 214 } 215 } else if (udev->ep[i]->type == EP_INTERRUPT) { 216 cdc->ep_int = udev->ep[i]; 217 } else { 218 continue; 219 } 220 } 221 222 char *buf = usb_malloc(CDC_READ_BUFFER_SIZE); 223 if (!buf) { 224 ZF_LOGD("Failed to allocate circular buffer!\n"); 225 usb_free(cdc); 226 return -1; 227 } 228 229 err = circ_buf_new(buf, CDC_READ_BUFFER_SIZE, &cdc->read_buf); 230 if (err) { 231 ZF_LOGD("Failed to allocate circular buffer!\n"); 232 usb_free(buf); 233 usb_free(cdc); 234 return -1; 235 } 236 237 class = usbdev_get_class(udev); 238 if (class != USB_CLASS_CDCDATA && class != USB_CLASS_COMM) { 239 ZF_LOGD("Not a CDC device(%d)\n", class); 240 circ_buf_free(&cdc->read_buf); 241 usb_free(buf); 242 usb_free(cdc); 243 return -1; 244 } 245 246 ZF_LOGD("USB CDC found, subclass(%x)\n", cdc->subclass); 247 248 /* Allocate read request */ 249 cdc->read_xact.type = PID_IN; 250 cdc->read_xact.len = CDC_READ_XACT_SIZE; 251 err = usb_alloc_xact(udev->dman, &cdc->read_xact, 1); 252 if (err) { 253 ZF_LOGF("Out of DMA memory\n"); 254 } 255 cdc->read_in_progress = 0; 256 257 /* Activate configuration */ 258 xact.len = sizeof(struct usbreq); 259 err = usb_alloc_xact(udev->dman, &xact, 1); 260 if (err) { 261 ZF_LOGF("Out of DMA memory\n"); 262 } 263 264 /* Fill in the request */ 265 xact.type = PID_SETUP; 266 req = xact_get_vaddr(&xact); 267 *req = __set_configuration_req(cdc->config); 268 269 /* Send the request to the host */ 270 err = usbdev_schedule_xact(udev, udev->ep_ctrl, &xact, 1, NULL, NULL); 271 if (err) { 272 ZF_LOGF("Transaction error\n"); 273 } 274 usb_destroy_xact(udev->dman, &xact, 1); 275 276 return 0; 277} 278 279int usb_cdc_read(usb_dev_t *udev, void *buf, int len) 280{ 281 int err; 282 int cnt = 0; 283 struct usb_cdc_device *cdc; 284 285 cdc = (struct usb_cdc_device*)udev->dev_data; 286 287 if (!cdc->read_in_progress) { 288 err = usbdev_schedule_xact(udev, cdc->ep_in, &cdc->read_xact, 1, 289 usb_cdc_read_cb, udev); 290 if (err) { 291 ZF_LOGF("Transaction error\n"); 292 } 293 sync_atomic_increment(&cdc->read_in_progress, __ATOMIC_RELAXED); 294 } 295 296 /* Get data from the read buffer */ 297 while (len--) { 298 if (!circ_buf_is_empty(&cdc->read_buf)) { 299 *((char*)buf + cnt) = circ_buf_get(&cdc->read_buf); 300 cnt++; 301 } else { 302 break; 303 } 304 } 305 306 return cnt; 307} 308 309int usb_cdc_write(usb_dev_t *udev, const void *buf, int len) 310{ 311 int err; 312 int cnt; 313 int offset; 314 struct usb_cdc_device *cdc; 315 struct xact *xact; 316 317 cdc = (struct usb_cdc_device*)udev->dev_data; 318 319 /* Xact needs to be virtually contiguous */ 320 cnt = ROUND_UP(len, MAX_XACT_SIZE) / MAX_XACT_SIZE; 321 322 xact = usb_malloc(sizeof(struct xact) * cnt); 323 if (!xact) { 324 ZF_LOGF("Out of memory\n"); 325 } 326 327 /* Fill in the length of each xact */ 328 for (int i = 0; i < cnt; i++) { 329 xact[i].type = PID_OUT; 330 xact[i].len = len < MAX_XACT_SIZE ? len : MAX_XACT_SIZE; 331 len -= xact[i].len; 332 } 333 334 /* DMA allocation */ 335 err = usb_alloc_xact(udev->dman, xact, cnt); 336 if (err) { 337 ZF_LOGF("Out of DMA memory\n"); 338 } 339 340 /* Copy in */ 341 offset = 0; 342 for (int i = 0; i < cnt; i++) { 343 memcpy(xact_get_vaddr(&xact[i]), (char*)buf + offset, xact[i].len); 344 offset += xact[i].len; 345 } 346 347 /* Send to the host */ 348 err = usbdev_schedule_xact(udev, cdc->ep_out, xact, cnt, NULL, NULL); 349 if (err) { 350 ZF_LOGF("Transaction error\n"); 351 } 352 353 /* Cleanup */ 354 usb_destroy_xact(udev->dman, xact, cnt); 355 356 usb_free(xact); 357 358 return len; 359} 360 361static void 362usb_cdc_mgmt_msg(struct usb_cdc_device *cdc, uint8_t req_type, 363 enum cdc_req_code code, int value, void *buf, int len) 364{ 365 int err; 366 struct usbreq *req; 367 struct xact msg[2]; 368 int cnt; 369 370 /* Allocate xact */ 371 msg[0].len = sizeof(struct usbreq); 372 msg[1].len = len; 373 err = usb_alloc_xact(cdc->udev->dman, msg, 2); 374 if (err) { 375 ZF_LOGF("Out of DMA memory\n"); 376 } 377 378 /* Management element request */ 379 msg[0].type = PID_SETUP; 380 req = xact_get_vaddr(&msg[0]); 381 req->bmRequestType = req_type; 382 req->bRequest = code; 383 req->wValue = value; 384 req->wIndex = cdc->comm; 385 req->wLength = len; 386 cnt = 1; 387 388 /* Data stage */ 389 if (len > 0) { 390 if (req_type & USB_DIR_IN) { 391 msg[1].type = PID_IN; 392 } else { 393 msg[1].type = PID_OUT; 394 } 395 memcpy(xact_get_vaddr(&msg[1]), buf, len); 396 cnt++; 397 } 398 399 /* Send to the host */ 400 err = usbdev_schedule_xact(cdc->udev, cdc->udev->ep_ctrl, 401 msg, cnt, NULL, NULL); 402 403 /* Copy out */ 404 if (len > 0 && msg[1].type == PID_IN) { 405 memcpy(xact_get_vaddr(&msg[1]), buf, len); 406 } 407 408 /* Cleanup */ 409 usb_destroy_xact(cdc->udev->dman, msg, 2); 410} 411 412/* Communication Device Class Requests */ 413void cdc_send_encap_cmd(usb_dev_t *udev, const void *buf, int len) 414{ 415 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 416 417 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 418 SEND_ENCAPSULATED_COMMAND, 0, (void*)buf, len); 419} 420 421void cdc_get_encap_resp(usb_dev_t *udev, void *buf, int len) 422{ 423 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 424 425 usb_cdc_mgmt_msg(cdc, USB_DIR_IN | USB_TYPE_CLS | USB_RCPT_INTERFACE, 426 GET_ENCAPSULATED_RESPONSE, 0, buf, len); 427} 428 429/* PSTN - Abstract Control Model Requests */ 430void acm_set_comm_feature(usb_dev_t *udev, enum acm_comm_feature f, 431 uint16_t state) 432{ 433 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 434 435 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 436 SET_COMM_FEATURE, f, &state, 2); 437} 438 439uint16_t acm_get_comm_feature(usb_dev_t *udev, enum acm_comm_feature f) 440{ 441 uint16_t state; 442 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 443 444 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 445 GET_COMM_FEATURE, f, &state, 2); 446 return state; 447} 448 449void acm_clear_comm_feature(usb_dev_t *udev, enum acm_comm_feature f) 450{ 451 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 452 453 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 454 CLEAR_COMM_FEATURE, f, NULL, 0); 455} 456 457void acm_set_line_coding(usb_dev_t *udev, const struct acm_line_coding *coding) 458{ 459 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 460 461 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 462 SET_LINE_CODING, 0, (struct acm_line_coding*)coding, 463 sizeof(*coding)); 464} 465 466void acm_get_line_coding(usb_dev_t *udev, struct acm_line_coding *coding) 467{ 468 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 469 470 usb_cdc_mgmt_msg(cdc, USB_DIR_IN | USB_TYPE_CLS | USB_RCPT_INTERFACE, 471 GET_LINE_CODING, 0, coding, sizeof(*coding)); 472} 473 474void acm_set_ctrl_line_state(usb_dev_t *udev, uint8_t ctrl) 475{ 476 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 477 478 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 479 SET_CONTROL_LINE_STATE, ctrl, NULL, 0); 480} 481 482void acm_send_break(usb_dev_t *udev, uint16_t us) 483{ 484 struct usb_cdc_device *cdc = (struct usb_cdc_device*)udev->dev_data; 485 486 usb_cdc_mgmt_msg(cdc, USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_INTERFACE, 487 SEND_BREAK, us, NULL, 0); 488} 489 490