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