00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "conf_usb_host.h"
00048 #include "USBHDriver.h"
00049 #include "USBDescriptors.h"
00050 #include "USBH.h"
00051 #include "CDCDescriptors.h"
00052 #include "uhi_cdc.h"
00053 #include <string.h>
00054
00055 #ifdef USB_HOST_HUB_SUPPORT
00056 # error USB HUB support is not implemented on UHI CDC
00057 #endif
00058
00059 #ifndef UHI_CDC_RX_NOTIFY
00060 # define UHI_CDC_RX_NOTIFY()
00061 #endif
00062
00063
00064 #ifdef UHI_CDC_LOW_RATE
00065 # define UHI_CDC_BUFFER_SIZE (1*64)
00066 #else
00067 # define UHI_CDC_BUFFER_SIZE (5*64)
00068 #endif
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 typedef struct {
00085
00086 uint16_t pos;
00087
00088 uint16_t nb;
00089
00090 uint8_t* ptr;
00091 } uhi_cdc_buf_t;
00092
00093
00094 typedef struct {
00095
00096 USBHS_Ep_t ep_data;
00097
00098 bool b_trans_ongoing;
00099
00100 uint16_t sof;
00101
00102 volatile uint8_t buf_sel;
00103
00104 uint16_t buffer_size;
00105
00106 uhi_cdc_buf_t buffer[2];
00107 } uhi_cdc_line_t;
00108
00109
00110 typedef struct {
00111
00112 CDCLineCoding conf;
00113
00114 uint8_t iface_comm;
00115
00116 uint8_t iface_data;
00117
00118 USBHS_Ep_t ep_comm_in;
00119
00120 uhi_cdc_line_t line_rx;
00121
00122 uhi_cdc_line_t line_tx;
00123 } uhi_cdc_port_t;
00124
00125
00126 typedef struct {
00127
00128 USBH_device_t *dev;
00129
00130 bool b_enabled;
00131
00132 uhi_cdc_port_t *port;
00133
00134 uint8_t nb_port;
00135 } uhi_cdc_dev_t;
00136
00137
00138 static uhi_cdc_dev_t uhi_cdc_dev = {
00139 .dev = NULL,
00140 .nb_port = 0,
00141 };
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 static void uhi_cdc_free_device(void);
00153
00154
00155
00156
00157
00158
00159
00160
00161 static uhi_cdc_port_t* uhi_cdc_get_port(uint8_t port_num);
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 static bool uhi_cdc_set_conf(uint8_t port, CDCLineCoding *configuration);
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 static bool uhi_cdc_set_ctrl_line(uint8_t port, uint16_t wValue);
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 static bool uhi_cdc_rx_update(uhi_cdc_line_t *line);
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 static void uhi_cdc_rx_received(USBHS_Add_t add, USBHS_Ep_t ep,
00205 USBH_XfrStatus_t status, uint32_t nb_transferred);
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 static bool uhi_cdc_tx_update(uhi_cdc_line_t *line);
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 static void uhi_cdc_tx_send(USBHS_Add_t add, USBHS_Ep_t ep,
00228 USBH_XfrStatus_t status, uint32_t nb_transferred);
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 USBH_enum_status_t uhi_cdc_install(USBH_device_t* dev)
00240 {
00241 bool b_iface_comm, b_iface_data;
00242 uint16_t conf_desc_lgt;
00243 uint8_t port_num, i;
00244 USBInterfaceDescriptor *ptr_iface;
00245 uhi_cdc_port_t *ptr_port = NULL;
00246 uhi_cdc_line_t *ptr_line;
00247
00248 if (uhi_cdc_dev.dev != NULL) {
00249 return UHC_ENUM_SOFTWARE_LIMIT;
00250 }
00251
00252
00253 conf_desc_lgt = (dev->conf_desc->wTotalLength);
00254 ptr_iface = (USBInterfaceDescriptor*)dev->conf_desc;
00255 uhi_cdc_dev.nb_port = 0;
00256 while (conf_desc_lgt) {
00257 if ((ptr_iface->bDescriptorType == USBGenericDescriptor_INTERFACE)
00258 && (ptr_iface->bInterfaceClass == CDCCommunicationInterfaceDescriptor_CLASS)
00259 && (ptr_iface->bInterfaceSubClass == CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL)
00260 && (ptr_iface->bInterfaceProtocol <= CDCCommunicationInterfaceDescriptor_NOPROTOCOL)) {
00261
00262 uhi_cdc_dev.nb_port++;
00263 }
00264 assert(conf_desc_lgt>=ptr_iface->bLength);
00265 conf_desc_lgt -= ptr_iface->bLength;
00266 ptr_iface = (USBInterfaceDescriptor*)((uint8_t*)ptr_iface + ptr_iface->bLength);
00267 }
00268 if (uhi_cdc_dev.nb_port == 0) {
00269 return UHC_ENUM_UNSUPPORTED;
00270 }
00271
00272
00273 uhi_cdc_dev.port = malloc(uhi_cdc_dev.nb_port * sizeof(uhi_cdc_port_t));
00274 if (uhi_cdc_dev.port == NULL) {
00275 assert(false);
00276 return UHC_ENUM_SOFTWARE_LIMIT;
00277 }
00278
00279 for (i = 0; i<uhi_cdc_dev.nb_port; i++) {
00280 uhi_cdc_dev.port[i].ep_comm_in = 0;
00281 uhi_cdc_dev.port[i].iface_data = 0xFF;
00282 uhi_cdc_dev.port[i].line_rx.ep_data = 0;
00283 uhi_cdc_dev.port[i].line_rx.buffer[0].ptr = NULL;
00284 uhi_cdc_dev.port[i].line_rx.buffer[1].ptr = NULL;
00285 uhi_cdc_dev.port[i].line_tx.ep_data = 0;
00286 uhi_cdc_dev.port[i].line_tx.buffer[0].ptr = NULL;
00287 uhi_cdc_dev.port[i].line_tx.buffer[1].ptr = NULL;
00288 }
00289
00290
00291 conf_desc_lgt = (dev->conf_desc->wTotalLength);
00292 ptr_iface = (USBInterfaceDescriptor*)dev->conf_desc;
00293 b_iface_comm = false;
00294 b_iface_data = false;
00295 port_num = 0;
00296 while (conf_desc_lgt) {
00297 switch (ptr_iface->bDescriptorType) {
00298
00299 case USBGenericDescriptor_INTERFACE:
00300 if ((ptr_iface->bInterfaceClass == CDCCommunicationInterfaceDescriptor_CLASS)
00301 && (ptr_iface->bInterfaceSubClass == CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL)
00302 && (ptr_iface->bInterfaceProtocol <= CDCCommunicationInterfaceDescriptor_NOPROTOCOL) )
00303 {
00304
00305 b_iface_comm = true;
00306 ptr_port = &uhi_cdc_dev.port[port_num++];
00307 ptr_port->iface_comm = ptr_iface->bInterfaceNumber;
00308 } else {
00309
00310 b_iface_comm = false;
00311 }
00312 if ((ptr_iface->bInterfaceClass == CDCDataInterfaceDescriptor_CLASS)
00313 && (ptr_iface->bInterfaceSubClass == 0)
00314 && (ptr_iface->bInterfaceProtocol == 0) ) {
00315 for (i = 0; i<uhi_cdc_dev.nb_port; i++) {
00316 ptr_port = &uhi_cdc_dev.port[i];
00317
00318 b_iface_data = true;
00319 break;
00320
00321
00322 if (ptr_port->iface_data == ptr_iface->bInterfaceNumber) {
00323
00324
00325 b_iface_data = true;
00326 break;
00327 }
00328 }
00329 } else {
00330
00331 b_iface_data = false;
00332 }
00333 break;
00334
00335 case CDCGenericDescriptor_INTERFACE:
00336 if (!b_iface_comm) {
00337 break;
00338 }
00339 if (((CDCCallManagementDescriptor*)ptr_iface)->bDescriptorSubtype == CDCGenericDescriptor_CALLMANAGEMENT) {
00340 ptr_port->iface_data = ((CDCCallManagementDescriptor*)ptr_iface)->bDataInterface;
00341 }
00342 break;
00343
00344 case USBGenericDescriptor_ENDPOINT:
00345
00346 if (b_iface_comm) {
00347 assert (((USBEndpointDescriptor *)ptr_iface)->bmAttributes == USBEndpointDescriptor_INTERRUPT);
00348 assert(((USBEndpointDescriptor*)ptr_iface)->bEndpointAddress & USB_EP_DIR_IN);
00349 if (!USBH_HAL_ConfigurePipe(dev->address, (USBEndpointDescriptor*)ptr_iface)) {
00350 uhi_cdc_free_device();
00351 return UHC_ENUM_HARDWARE_LIMIT;
00352 }
00353 ptr_port->ep_comm_in = ((USBEndpointDescriptor*)ptr_iface)->bEndpointAddress;
00354 }
00355 if (b_iface_data) {
00356 assert (((USBEndpointDescriptor*)ptr_iface)->bmAttributes == USBEndpointDescriptor_BULK);
00357 if (!USBH_HAL_ConfigurePipe(dev->address, (USBEndpointDescriptor*)ptr_iface)) {
00358 uhi_cdc_free_device();
00359 return UHC_ENUM_HARDWARE_LIMIT;
00360 }
00361
00362 if (((USBEndpointDescriptor*)ptr_iface)->bEndpointAddress & USB_EP_DIR_IN) {
00363 ptr_line = &ptr_port->line_rx;
00364 } else {
00365 ptr_line = &ptr_port->line_tx;
00366 }
00367 ptr_line->ep_data = ((USBEndpointDescriptor*)ptr_iface)->bEndpointAddress;
00368 ptr_line->b_trans_ongoing = false;
00369 ptr_line->buf_sel = 0;
00370
00371
00372 uint16_t buf_size = Max( (
00373 ((USBEndpointDescriptor*)ptr_iface)->wMaxPacketSize),
00374 UHI_CDC_BUFFER_SIZE );
00375 ptr_line->buffer_size = buf_size;
00376 ptr_line->buffer[0].pos = 0;
00377 ptr_line->buffer[0].nb = 0;
00378 ptr_line->buffer[0].ptr = malloc(buf_size);
00379 if (ptr_line->buffer[0].ptr == NULL) {
00380 assert(false);
00381 uhi_cdc_free_device();
00382 return UHC_ENUM_SOFTWARE_LIMIT;
00383 }
00384 ptr_line->buffer[1].pos = 0;
00385 ptr_line->buffer[1].nb = 0;
00386 ptr_line->buffer[1].ptr = malloc(buf_size);
00387 if (ptr_line->buffer[1].ptr == NULL) {
00388 assert(false);
00389 uhi_cdc_free_device();
00390 return UHC_ENUM_SOFTWARE_LIMIT;
00391 }
00392
00393 }
00394 break;
00395
00396 }
00397 assert(conf_desc_lgt >= ptr_iface->bLength);
00398 conf_desc_lgt -= ptr_iface->bLength;
00399 ptr_iface = (USBInterfaceDescriptor*)((uint8_t*)ptr_iface + ptr_iface->bLength);
00400 }
00401
00402
00403 for (i = 0; i<uhi_cdc_dev.nb_port; i++) {
00404 if ((uhi_cdc_dev.port[i].ep_comm_in == 0)
00405 || (uhi_cdc_dev.port[i].line_rx.ep_data == 0)
00406 || (uhi_cdc_dev.port[i].line_tx.ep_data == 0)) {
00407
00408 uhi_cdc_free_device();
00409 return UHC_ENUM_UNSUPPORTED;
00410 }
00411 }
00412 uhi_cdc_dev.b_enabled = false;
00413 uhi_cdc_dev.dev = dev;
00414 return UHC_ENUM_SUCCESS;
00415 }
00416
00417 void uhi_cdc_enable(USBH_device_t* dev)
00418 {
00419 if (uhi_cdc_dev.dev != dev) {
00420 return;
00421 }
00422 uhi_cdc_dev.b_enabled = true;
00423
00424
00425 uhi_cdc_sof(false);
00426 UHI_CDC_CHANGE(dev,true);
00427 }
00428
00429 void uhi_cdc_uninstall(USBH_device_t* dev)
00430 {
00431 if (uhi_cdc_dev.dev != dev) {
00432 return;
00433 }
00434 uhi_cdc_dev.dev = NULL;
00435 uhi_cdc_free_device();
00436 UHI_CDC_CHANGE(dev,false);
00437 }
00438
00439 void uhi_cdc_sof(bool b_micro)
00440 {
00441 uint8_t port = 0;
00442 uhi_cdc_port_t *ptr_port;
00443 UNUSED(b_micro);
00444
00445 if (uhi_cdc_dev.dev == NULL) {
00446 return;
00447 }
00448 if (!uhi_cdc_dev.b_enabled) {
00449 return;
00450 }
00451
00452
00453 while (1) {
00454 ptr_port = uhi_cdc_get_port(port++);
00455 if (ptr_port == NULL) {
00456 break;
00457 }
00458 uhi_cdc_rx_update(&ptr_port->line_rx);
00459 uhi_cdc_tx_update(&ptr_port->line_tx);
00460 }
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470 static void uhi_cdc_free_device(void)
00471 {
00472 if (uhi_cdc_dev.port == NULL) {
00473 return;
00474 }
00475
00476 uint8_t i;
00477 for ( i=0;i<uhi_cdc_dev.nb_port; i++) {
00478 if (uhi_cdc_dev.port[i].line_rx.buffer[0].ptr) {
00479 free(uhi_cdc_dev.port[i].line_rx.buffer[0].ptr);
00480 }
00481 if (uhi_cdc_dev.port[i].line_rx.buffer[1].ptr) {
00482 free(uhi_cdc_dev.port[i].line_rx.buffer[1].ptr);
00483 }
00484 if (uhi_cdc_dev.port[i].line_tx.buffer[0].ptr) {
00485 free(uhi_cdc_dev.port[i].line_tx.buffer[0].ptr);
00486 }
00487 if (uhi_cdc_dev.port[i].line_tx.buffer[1].ptr) {
00488 free(uhi_cdc_dev.port[i].line_tx.buffer[1].ptr);
00489 }
00490 }
00491 free(uhi_cdc_dev.port);
00492 }
00493
00494 static uhi_cdc_port_t* uhi_cdc_get_port(uint8_t port_num)
00495 {
00496 if (uhi_cdc_dev.dev == NULL) {
00497 return NULL;
00498 }
00499 if (port_num >= uhi_cdc_dev.nb_port) {
00500 return NULL;
00501 }
00502 return &uhi_cdc_dev.port[port_num];
00503 }
00504
00505 static bool uhi_cdc_set_conf(uint8_t port, CDCLineCoding *configuration)
00506 {
00507 uhi_cdc_port_t *ptr_port;
00508 USBGenericRequest req;
00509
00510
00511 ptr_port = uhi_cdc_get_port(port);
00512 if (ptr_port == NULL) {
00513 return false;
00514 }
00515 memcpy(&ptr_port->conf, configuration, sizeof(CDCLineCoding));
00516
00517
00518 req.bmRequestType = USB_REQ_RECIP_INTERFACE | USB_REQ_TYPE_CLASS | USB_REQ_DIR_OUT;
00519 req.bRequest = CDCGenericRequest_SETLINECODING;
00520 req.wValue = 0;
00521 req.wIndex = ptr_port->iface_comm;
00522 req.wLength = sizeof(CDCLineCoding);
00523 if (!USBH_HAL_SetupReq(uhi_cdc_dev.dev->address,
00524 &req,
00525 (uint8_t *) &ptr_port->conf,
00526 sizeof(CDCLineCoding),
00527 NULL, NULL)) {
00528 return false;
00529 }
00530 return true;
00531 }
00532
00533 static bool uhi_cdc_set_ctrl_line(uint8_t port, uint16_t wValue)
00534 {
00535 uhi_cdc_port_t *ptr_port;
00536 USBGenericRequest req;
00537
00538
00539 ptr_port = uhi_cdc_get_port(port);
00540 if (ptr_port == NULL) {
00541 return false;
00542 }
00543
00544
00545 req.bmRequestType = USB_REQ_RECIP_INTERFACE | USB_REQ_TYPE_CLASS | USB_REQ_DIR_OUT;
00546 req.bRequest = CDCGenericRequest_SETCONTROLLINESTATE;
00547 req.wValue = wValue;
00548 req.wIndex = ptr_port->iface_comm;
00549 req.wLength = 0;
00550 if (!USBH_HAL_SetupReq(uhi_cdc_dev.dev->address,
00551 &req,
00552 NULL,
00553 0,
00554 NULL, NULL)) {
00555 return false;
00556 }
00557 return true;
00558 }
00559
00560 static bool uhi_cdc_rx_update(uhi_cdc_line_t *line)
00561 {
00562 irqflags_t flags;
00563 uhi_cdc_buf_t *buf_nosel;
00564 uhi_cdc_buf_t *buf_sel;
00565
00566 flags = cpu_irq_save();
00567
00568 if (line->b_trans_ongoing) {
00569 cpu_irq_restore(flags);
00570 return false;
00571 }
00572
00573
00574 buf_sel = &line->buffer[line->buf_sel];
00575 buf_nosel = &line->buffer[(line->buf_sel == 0)? 1 : 0];
00576 if (buf_sel->pos >= buf_sel->nb) {
00577
00578
00579 buf_sel->pos = 0;
00580 buf_sel->nb = 0;
00581 }
00582 if (!buf_sel->nb && buf_nosel->nb) {
00583
00584 line->buf_sel = (line->buf_sel == 0)? 1 : 0;
00585 buf_nosel = buf_sel;
00586 UHI_CDC_RX_NOTIFY();
00587 }
00588
00589 if (buf_nosel->nb) {
00590
00591 cpu_irq_restore(flags);
00592 return false;
00593 }
00594
00595
00596 if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
00597 if (line->sof == USBH_HAL_GetMicroFrameNum()) {
00598 cpu_irq_restore(flags);
00599 return false;
00600 }
00601 } else {
00602 if (line->sof == USBH_HAL_GetFrameNum()) {
00603 cpu_irq_restore(flags);
00604 return false;
00605 }
00606 }
00607
00608
00609 line->b_trans_ongoing = true;
00610 cpu_irq_restore(flags);
00611
00612 return USBH_HAL_RunEndpoint(
00613 uhi_cdc_dev.dev->address,
00614 line->ep_data,
00615 true,
00616 buf_nosel->ptr,
00617 line->buffer_size,
00618 10,
00619 uhi_cdc_rx_received);
00620 }
00621
00622 static void uhi_cdc_rx_received(
00623 USBHS_Add_t add,
00624 USBHS_Ep_t ep,
00625 USBH_XfrStatus_t status,
00626 uint32_t nb_transferred)
00627 {
00628 uint8_t port = 0;
00629 uhi_cdc_port_t *ptr_port;
00630 uhi_cdc_line_t *line;
00631 uhi_cdc_buf_t *buf;
00632 UNUSED(add);
00633
00634
00635 while (1) {
00636 ptr_port = uhi_cdc_get_port(port++);
00637 if (ptr_port == NULL) {
00638 return;
00639 }
00640 line = &ptr_port->line_rx;
00641 if (ep == line->ep_data) {
00642 break;
00643 }
00644 }
00645
00646 if (UHD_TRANS_NOERROR != status) {
00647
00648 line->b_trans_ongoing = false;
00649 return;
00650 }
00651
00652
00653 if (nb_transferred != line->buffer_size) {
00654 if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
00655 line->sof = USBH_HAL_GetMicroFrameNum();
00656 } else {
00657 line->sof = USBH_HAL_GetFrameNum();
00658 }
00659 }
00660
00661
00662 buf = &line->buffer[(line->buf_sel == 0) ? 1 : 0];
00663 buf->pos = 0;
00664 buf->nb = nb_transferred;
00665 line->b_trans_ongoing = false;
00666
00667
00668 uhi_cdc_rx_update(line);
00669 }
00670
00671
00672 static bool uhi_cdc_tx_update(uhi_cdc_line_t *line)
00673 {
00674 irqflags_t flags;
00675 uhi_cdc_buf_t *buf;
00676
00677 flags = cpu_irq_save();
00678
00679 if (line->b_trans_ongoing) {
00680 cpu_irq_restore(flags);
00681 return false;
00682 }
00683
00684 if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
00685 if (line->sof == USBH_HAL_GetMicroFrameNum()) {
00686 cpu_irq_restore(flags);
00687 return false;
00688 }
00689 } else {
00690 if (line->sof == USBH_HAL_GetFrameNum()) {
00691 cpu_irq_restore(flags);
00692 return false;
00693 }
00694 }
00695
00696
00697 buf = &line->buffer[line->buf_sel];
00698 if (buf->nb == 0) {
00699 cpu_irq_restore(flags);
00700 return false;
00701 }
00702
00703
00704 line->buf_sel = (line->buf_sel == 0)? 1 : 0;
00705
00706
00707 line->b_trans_ongoing = true;
00708 cpu_irq_restore(flags);
00709
00710 return USBH_HAL_RunEndpoint(
00711 uhi_cdc_dev.dev->address,
00712 line->ep_data,
00713 true,
00714 buf->ptr,
00715 buf->nb,
00716 1000,
00717 uhi_cdc_tx_send);
00718 }
00719
00720
00721 static void uhi_cdc_tx_send(
00722 USBHS_Add_t add,
00723 USBHS_Ep_t ep,
00724 USBH_XfrStatus_t status,
00725 uint32_t nb_transferred)
00726 {
00727 uint8_t port = 0;
00728 uhi_cdc_port_t *ptr_port;
00729 uhi_cdc_line_t *line;
00730 uhi_cdc_buf_t *buf;
00731 irqflags_t flags;
00732 UNUSED(add);
00733
00734 flags = cpu_irq_save();
00735
00736
00737 while (1) {
00738 ptr_port = uhi_cdc_get_port(port++);
00739 if (ptr_port == NULL) {
00740 cpu_irq_restore(flags);
00741 return;
00742 }
00743 line = &ptr_port->line_tx;
00744 if (ep == line->ep_data) {
00745 break;
00746 }
00747 }
00748
00749 if (UHD_TRANS_NOERROR != status) {
00750
00751 line->b_trans_ongoing = false;
00752 cpu_irq_restore(flags);
00753 return;
00754 }
00755
00756
00757 if (nb_transferred != line->buffer_size) {
00758 if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
00759 line->sof = USBH_HAL_GetMicroFrameNum();
00760 } else {
00761 line->sof = USBH_HAL_GetFrameNum();
00762 }
00763 }
00764
00765
00766 buf = &line->buffer[(line->buf_sel == 0) ? 1 : 0 ];
00767 buf->nb = 0;
00768 line->b_trans_ongoing = false;
00769 cpu_irq_restore(flags);
00770
00771
00772 uhi_cdc_tx_update(line);
00773 }
00774
00775
00776
00777 bool uhi_cdc_open(uint8_t port, CDCLineCoding *configuration)
00778 {
00779
00780 if (!uhi_cdc_set_conf(port, configuration)) {
00781 return false;
00782 }
00783
00784 if (!uhi_cdc_set_ctrl_line(port, CDCControlLineState_DTE_PRESENT)) {
00785 return false;
00786 }
00787 return true;
00788 }
00789
00790 void uhi_cdc_close(uint8_t port)
00791 {
00792
00793 uhi_cdc_set_ctrl_line(port, 0);
00794 }
00795
00796 bool uhi_cdc_is_rx_ready(uint8_t port)
00797 {
00798 return (0 != uhi_cdc_get_nb_received(port));
00799 }
00800
00801 uint32_t uhi_cdc_get_nb_received(uint8_t port)
00802 {
00803 uhi_cdc_port_t *ptr_port;
00804 uhi_cdc_buf_t *buf;
00805
00806
00807 ptr_port = uhi_cdc_get_port(port);
00808 if (ptr_port == NULL) {
00809 return false;
00810 }
00811
00812
00813 buf = &ptr_port->line_rx.buffer[ ptr_port->line_rx.buf_sel ];
00814 return (buf->nb - buf->pos);
00815 }
00816
00817 int uhi_cdc_getc(uint8_t port)
00818 {
00819 uhi_cdc_port_t *ptr_port;
00820 uhi_cdc_line_t *line;
00821 uhi_cdc_buf_t *buf;
00822 int rx_data = 0;
00823 bool b_databit_9;
00824
00825
00826 ptr_port = uhi_cdc_get_port(port);
00827 if (ptr_port == NULL) {
00828 return false;
00829 }
00830 line = &ptr_port->line_rx;
00831
00832 b_databit_9 = (9 == ptr_port->conf.bDataBits);
00833
00834 uhi_cdc_getc_process_one_byte:
00835
00836 buf = &line->buffer[line->buf_sel];
00837 while (buf->pos >= buf->nb) {
00838 if (NULL == uhi_cdc_get_port(port)) {
00839 return 0;
00840 }
00841 uhi_cdc_rx_update(line);
00842 goto uhi_cdc_getc_process_one_byte;
00843 }
00844
00845
00846 rx_data |= buf->ptr[buf->pos];
00847 buf->pos++;
00848
00849 uhi_cdc_rx_update(line);
00850
00851 if (b_databit_9) {
00852
00853 b_databit_9 = false;
00854 rx_data = rx_data << 8;
00855 goto uhi_cdc_getc_process_one_byte;
00856 }
00857 return rx_data;
00858 }
00859
00860 uint32_t uhi_cdc_read_buf(uint8_t port, void* buf, uint32_t size)
00861 {
00862 uhi_cdc_port_t *ptr_port;
00863 uhi_cdc_line_t *line;
00864 uhi_cdc_buf_t *cdc_buf;
00865 uint32_t copy_nb;
00866
00867
00868 ptr_port = uhi_cdc_get_port(port);
00869 if (ptr_port == NULL) {
00870 return false;
00871 }
00872 line = &ptr_port->line_rx;
00873
00874
00875 uhi_cdc_read_buf_loop_wait:
00876
00877 cdc_buf = &line->buffer[line->buf_sel];
00878 while (cdc_buf->pos >= cdc_buf->nb) {
00879 if (NULL == uhi_cdc_get_port(port)) {
00880 return 0;
00881 }
00882 uhi_cdc_rx_update(line);
00883 goto uhi_cdc_read_buf_loop_wait;
00884 }
00885
00886
00887 copy_nb = cdc_buf->nb - cdc_buf->pos;
00888 if (copy_nb > size) {
00889 copy_nb = size;
00890 }
00891 memcpy(buf, &cdc_buf->ptr[cdc_buf->pos], copy_nb);
00892 cdc_buf->pos += copy_nb;
00893 buf = (uint8_t*)buf + copy_nb;
00894 size -= copy_nb;
00895
00896 uhi_cdc_rx_update(line);
00897
00898 if (size) {
00899 goto uhi_cdc_read_buf_loop_wait;
00900 }
00901 return 0;
00902 }
00903
00904
00905 bool uhi_cdc_is_tx_ready(uint8_t port)
00906 {
00907 uhi_cdc_port_t *ptr_port;
00908 uhi_cdc_line_t *line;
00909
00910 ptr_port = uhi_cdc_get_port(port);
00911 if (ptr_port == NULL) {
00912 return false;
00913 }
00914 line = &ptr_port->line_tx;
00915
00916 return (line->buffer_size != line->buffer[line->buf_sel].nb);
00917 }
00918
00919
00920 int uhi_cdc_putc(uint8_t port, int value)
00921 {
00922 irqflags_t flags;
00923 uhi_cdc_port_t *ptr_port;
00924 uhi_cdc_line_t *line;
00925 uhi_cdc_buf_t *buf;
00926 bool b_databit_9;
00927
00928
00929 ptr_port = uhi_cdc_get_port(port);
00930 if (ptr_port == NULL) {
00931 return false;
00932 }
00933 line = &ptr_port->line_tx;
00934
00935 b_databit_9 = (9 == ptr_port->conf.bDataBits);
00936
00937 uhi_cdc_putc_process_one_byte:
00938
00939 buf = &line->buffer[line->buf_sel];
00940 while (line->buffer_size == buf->nb) {
00941 if (NULL == uhi_cdc_get_port(port)) {
00942 return false;
00943 }
00944 goto uhi_cdc_putc_process_one_byte;
00945 }
00946
00947
00948 flags = cpu_irq_save();
00949 buf = &line->buffer[line->buf_sel];
00950 buf->ptr[buf->nb++] = value;
00951 cpu_irq_restore(flags);
00952
00953 if (b_databit_9) {
00954
00955 b_databit_9 = false;
00956 value = value >> 8;
00957 goto uhi_cdc_putc_process_one_byte;
00958 }
00959 return true;
00960 }
00961
00962 uint32_t uhi_cdc_write_buf(uint8_t port, const void* buf, uint32_t size)
00963 {
00964 irqflags_t flags;
00965 uhi_cdc_port_t *ptr_port;
00966 uhi_cdc_line_t *line;
00967 uhi_cdc_buf_t *cdc_buf;
00968 uint32_t copy_nb;
00969
00970
00971 ptr_port = uhi_cdc_get_port(port);
00972 if (ptr_port == NULL) {
00973 return false;
00974 }
00975 line = &ptr_port->line_tx;
00976
00977 if (9 == ptr_port->conf.bDataBits) {
00978 size *=2;
00979 }
00980
00981 uhi_cdc_write_buf_loop_wait:
00982
00983 cdc_buf = &line->buffer[line->buf_sel];
00984 while (line->buffer_size == cdc_buf->nb) {
00985 if (NULL == uhi_cdc_get_port(port)) {
00986 return 0;
00987 }
00988 goto uhi_cdc_write_buf_loop_wait;
00989 }
00990
00991
00992 flags = cpu_irq_save();
00993 cdc_buf = &line->buffer[line->buf_sel];
00994 copy_nb = line->buffer_size - cdc_buf->nb;
00995 if (copy_nb>size) {
00996 copy_nb = size;
00997 }
00998 memcpy(&cdc_buf->ptr[cdc_buf->nb], buf, copy_nb);
00999 cdc_buf->nb += copy_nb;
01000 cpu_irq_restore(flags);
01001
01002
01003 buf = (uint8_t*)buf + copy_nb;
01004 size -= copy_nb;
01005
01006 if (size) {
01007 goto uhi_cdc_write_buf_loop_wait;
01008 }
01009
01010 return 0;
01011 }
01012
01013