From a54ad9edce697133a024aff096e50f7e4f389d5b Mon Sep 17 00:00:00 2001 From: Florent Duchon Date: Sun, 18 Mar 2012 12:22:02 +0100 Subject: digital/beacon: import Zigbit stack (bitcloud) & avr sources --- .../drivers/USBClasses/VCP/src/vcpVirtualUsart.c | 498 +++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 digital/beacon/src/Bitcloud_stack/Components/HAL/drivers/USBClasses/VCP/src/vcpVirtualUsart.c (limited to 'digital/beacon/src/Bitcloud_stack/Components/HAL/drivers/USBClasses/VCP/src/vcpVirtualUsart.c') diff --git a/digital/beacon/src/Bitcloud_stack/Components/HAL/drivers/USBClasses/VCP/src/vcpVirtualUsart.c b/digital/beacon/src/Bitcloud_stack/Components/HAL/drivers/USBClasses/VCP/src/vcpVirtualUsart.c new file mode 100644 index 00000000..29469576 --- /dev/null +++ b/digital/beacon/src/Bitcloud_stack/Components/HAL/drivers/USBClasses/VCP/src/vcpVirtualUsart.c @@ -0,0 +1,498 @@ +/****************************************************************************//** + \file vcpVirtualUart.c + + \brief Implementation of virtual uart API. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 11/09/08 A. Khromykh - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include + +/****************************************************************************** + Types section +******************************************************************************/ +// usart control +typedef struct +{ + uint16_t rxUnusedRemaining; +} VcpControl_t; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +/****************************************************************************** +Tuning of received buffer and enable received pipe if there is free place +in the buffer. +Parameters: + descriptor - pointer to HAL_UartDescriptor_t structure; +Returns: + none. +******************************************************************************/ +void vcpEnableReadPipe(void); + +/****************************************************************************** + External global variables section +******************************************************************************/ +extern UsbCdcRequest_t request; +extern UsbCdcResponse_t response; + +/****************************************************************************** + Global variables section +******************************************************************************/ +// pointer to application uart descriptor +HAL_UsartDescriptor_t *vcpPointDescrip = NULL; +// structure for internal ring buffer +VcpControl_t vcpControl; + +/****************************************************************************** + Implementations section +******************************************************************************/ +/****************************************************************************** +Transmitting callback of virtual uart +Parameters: + pArg - pointer to some data. + status - result of the USB transfer. + transferred - how much data are transferred + remaining - how much data are not transferred +Returns: + none. +******************************************************************************/ +void vcpTmtCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining) +{ + (void)pArg; + (void)status; + (void)remaining; + uint16_t copyPor = vcpPointDescrip->service.txPointOfRead; + uint16_t copyPow = vcpPointDescrip->service.txPointOfWrite; + bool endOfTransferring = true; + + if (NULL != vcpPointDescrip) + { + if (NULL != vcpPointDescrip->txBuffer) + { /* polling mode */ + copyPor += transferred; + if (copyPor == vcpPointDescrip->txBufferLength) + copyPor = 0; + + if (copyPor != copyPow) + { + if (copyPor > copyPow) + { + HAL_UsbWrite(VCP_TRANSMIT_PIPE, &vcpPointDescrip->txBuffer[copyPor], + (vcpPointDescrip->txBufferLength - copyPor), vcpTmtCallback, NULL); + } + else + { + HAL_UsbWrite(VCP_TRANSMIT_PIPE, &vcpPointDescrip->txBuffer[copyPor], + (copyPow - copyPor), vcpTmtCallback, NULL); + } + } + endOfTransferring = false; + vcpPointDescrip->service.txPointOfRead = copyPor; + } /* polling mode */ + + if (!endOfTransferring) + return; + + if (!(transferred % BULK_SIZE) && transferred) + { + /* + Universal Serial Bus Class Definitions for Communication Devices + 3.8.1.1 Segment Delineation + This positive delineation is done using a USB short packet mechanism. When a segment spans N USB packets, the + first packet through packet N-1 shall be the maximum packet size defined for the USB endpoint. If the Nth packet is + less than maximum packet size the USB transfer of this short packet will identify the end of the segment. If the Nth + packet is exactly maximum packet size, it shall be followed by a zero-length packet (which is a short packet) to assure + the end of segment is properly identified. + When transmitting data to the networking device, it is assumed that the client of the host USB driver takes the + appropriate actions to cause a short packet to be sent to the networking device. For segments with lengths that are an + even multiple of the pipe’s “max packet size”, the ability to write a buffer of zero length is required to generate this + short packet. + */ + HAL_UsbWrite(VCP_TRANSMIT_PIPE, NULL, 0, vcpTmtCallback, NULL); + } + else + { + if (NULL != vcpPointDescrip->txCallback) + vcpPointDescrip->txCallback(); + } + + } +} + +/****************************************************************************** +Receiving callback of virtual uart +Parameters: + pArg - pointer to something data. + status - result of the USB transfer. + transferred - how much data are transferred + remaining - how much data are not transferred +Returns: + none. +******************************************************************************/ +void vcpRcvCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining) +{ + (void)pArg; + (void)status; + (void)remaining; + uint16_t number; + uint16_t copyPor; + uint16_t copyPow; + uint16_t copyUnr; + + vcpPointDescrip->service.rxPointOfWrite += transferred; + copyPor = vcpPointDescrip->service.rxPointOfRead; + copyPow = vcpPointDescrip->service.rxPointOfWrite; + copyUnr = vcpControl.rxUnusedRemaining; + + if (NULL != vcpPointDescrip) + { + if (NULL != vcpPointDescrip->rxCallback) + { + if (copyPow < copyPor) + number = copyUnr - (copyPor - copyPow); + else + number = copyPow - copyPor; + + vcpPointDescrip->rxCallback(number); + vcpEnableReadPipe(); + } + } +} + +/****************************************************************************** +Open virtual com port and register uart's event handlers. + +Parameters: + descriptor - pointer to HAL_UartDescriptor_t structure + +Returns: + Returns positive uart descriptor on success or -1 in cases: + - bad uart channel; + - there are not enough resources; + - receiving buffer is less bulk endpoint size; +******************************************************************************/ +int VCP_OpenUsart(HAL_UsartDescriptor_t *descriptor) +{ + if (NULL == descriptor) + return -1; + + if (USART_CHANNEL_VCP != descriptor->tty) + return -1; + + if (NULL != vcpPointDescrip) + return -1; /* source was opened */ + + vcpPointDescrip = descriptor; + + vcpPointDescrip->service.rxPointOfRead = 0; + vcpPointDescrip->service.rxPointOfWrite = 0; + vcpControl.rxUnusedRemaining = vcpPointDescrip->rxBufferLength; + vcpPointDescrip->service.txPointOfRead = 0; + vcpPointDescrip->service.txPointOfWrite = 0; + HAL_RegisterEndOfBusResetHandler(usbBusResetAction); + if (DEVICE_POWERED != HAL_GetState()) + HAL_UsbInit((uint8_t *)&request); + + return (int)descriptor->tty; +} + +/****************************************************************************** +Frees the virtual uart channel. +Parameters: + descriptor - the uart descriptor. +Returns: + Returns 0 on success or -1 if bad descriptor. +******************************************************************************/ +int VCP_CloseUsart(HAL_UsartDescriptor_t *descriptor) +{ + if (NULL == descriptor) + return -1; + + if (vcpPointDescrip != descriptor) + return -1; + + vcpPointDescrip = NULL; + + return 0; +} + +/****************************************************************************** +Writes a number of bytes to a virtual uart channel. +txCallback function will be used to notify when the transmission is finished. +Parameters: + descriptor - pointer to HAL_UartDescriptor_t structure; + buffer - pointer to the application data buffer; + length - number of bytes to transfer; +Returns: + -1 - bad descriptor; + Number of bytes placed to the buffer - success. +******************************************************************************/ +int VCP_WriteUsart(HAL_UsartDescriptor_t *descriptor, uint8_t *buffer, uint16_t length) +{ + uint16_t copyPow = vcpPointDescrip->service.txPointOfWrite; + uint16_t copyPor = vcpPointDescrip->service.txPointOfRead; + uint16_t freePlace; + uint16_t wasWrote = 0; + + if (NULL == descriptor) + return -1; + + if (vcpPointDescrip != descriptor) + return -1; + + if (!buffer || !length) + return -1; + + if (NULL == descriptor->txBuffer) + { /* callback mode */ + if (STATUS_SUCCESS != HAL_UsbWrite(VCP_TRANSMIT_PIPE, buffer, length, vcpTmtCallback, NULL)) + return -1; // there is unsent data + return length; + } /* callback mode */ + else + { /* polling mode */ + if (copyPor > copyPow) + { + freePlace = copyPor - copyPow; + if (freePlace < length) + return -1; // there is unsent data + memcpy(&descriptor->txBuffer[copyPow], buffer, length); + HAL_UsbWrite(VCP_TRANSMIT_PIPE, buffer, length, vcpTmtCallback, NULL); + copyPow += length; + + } + else // point of write more or equal point of read + { + freePlace = descriptor->txBufferLength - copyPow + copyPor; + if (freePlace < length) + return -1; // there is unsent data + + uint16_t tempValue = descriptor->txBufferLength - copyPow; + if (length > tempValue) + { + memcpy(&descriptor->txBuffer[copyPow], buffer, tempValue); + HAL_UsbWrite(VCP_TRANSMIT_PIPE, buffer, tempValue, vcpTmtCallback, NULL); + buffer += tempValue; + length -= tempValue; + memcpy(descriptor->txBuffer, buffer, length); + copyPow = length; + } + else + { + memcpy(&descriptor->txBuffer[copyPow], buffer, length); + HAL_UsbWrite(VCP_TRANSMIT_PIPE, buffer, length, vcpTmtCallback, NULL); + copyPow += length; + } + } + + if (copyPow == descriptor->txBufferLength) + copyPow = 0; + vcpPointDescrip->service.txPointOfWrite = copyPow; + wasWrote = length; + + return wasWrote; + } /* polling mode */ +} + +/****************************************************************************** +Tuning of received buffer and enable received pipe if there is free place +in the buffer. +Parameters: + none; +Returns: + none. +******************************************************************************/ +void vcpEnableReadPipe(void) +{ + uint16_t copyPor = vcpPointDescrip->service.rxPointOfRead; + uint16_t copyPow = vcpPointDescrip->service.rxPointOfWrite; + uint16_t copyUnr = vcpControl.rxUnusedRemaining; + uint8_t usbResult = STATUS_SUCCESS; + + do + { + if (copyPor < copyPow) + { + if ((vcpPointDescrip->rxBufferLength - copyPow) < BULK_SIZE) + { + copyUnr = copyPow; + if (0 == copyPor) + { + usbResult = STATUS_BUSY; + break; + } + copyPow = 0; + } + else + { + usbResult = HAL_UsbRead(VCP_RECEIVE_PIPE, &vcpPointDescrip->rxBuffer[copyPow], BULK_SIZE, vcpRcvCallback, NULL); + break; + } + } + else + { + // empty buffer + if (copyPow == copyPor) + { + if ((vcpPointDescrip->rxBufferLength - copyPow) < BULK_SIZE) + { + copyUnr = vcpPointDescrip->rxBufferLength; + copyPor = 0; + copyPow = 0; + } + usbResult = HAL_UsbRead(VCP_RECEIVE_PIPE, &vcpPointDescrip->rxBuffer[copyPow], BULK_SIZE, vcpRcvCallback, NULL); + } // copyPor > copyPow + else + { + if ((copyPor - copyPow) >= BULK_SIZE) + usbResult = HAL_UsbRead(VCP_RECEIVE_PIPE, &vcpPointDescrip->rxBuffer[copyPow], BULK_SIZE, vcpRcvCallback, NULL); + else + usbResult = STATUS_BUSY; + } + break; + } + } while(1); + + if (STATUS_SUCCESS == usbResult) + { + vcpPointDescrip->service.rxPointOfRead = copyPor; + vcpPointDescrip->service.rxPointOfWrite = copyPow; + vcpControl.rxUnusedRemaining = copyUnr; + } +} + +/***************************************************************************** +Reads length bytes from uart and places ones to buffer. +Parameters: + descriptor - uart descriptor; + buffer - pointer to a application buffer; + length - the number of bytes which should be placed to buffer +Returns: + -1 - bad descriptor, bad number to read; + number of bytes that were placed to buffer. +*****************************************************************************/ +int VCP_ReadUsart(HAL_UsartDescriptor_t *descriptor, uint8_t *buffer, uint16_t length) +{ + uint16_t wasRead = 0; + uint16_t firstPart = 0; + uint16_t copyPor = vcpPointDescrip->service.rxPointOfRead; + uint16_t copyPow = vcpPointDescrip->service.rxPointOfWrite; + uint16_t copyUnr = vcpControl.rxUnusedRemaining; + + if (NULL == descriptor) + return -1; + + if (vcpPointDescrip != descriptor) + return -1; + + if (!buffer || !length) + return -1; + + do + { + // buffer is empty + if (copyPow == copyPor) + break; + + // [----**********---------] --- empty **** busy + // por pow + // [*****---------*******###] ### unused at the current moment + // pow por ur + // por - point of read(user read from buffer) + // pow - point of write(HAL write to buffer) + // ur - unused remaining(because remaining less then max packet size at the start read moment.) + if (copyPor < copyPow) + { + wasRead = copyPow - copyPor; + + if (wasRead > length) + { + wasRead = length; + memcpy(buffer, &vcpPointDescrip->rxBuffer[copyPor], wasRead); + copyPor += length; + } + else + { + memcpy(buffer, &vcpPointDescrip->rxBuffer[copyPor], wasRead); + copyPor = copyPow; + } + break; + } + else //copyPor > copyPow + { + if ((copyPor + length) < copyUnr) + { + wasRead = length; + memcpy(buffer, &vcpPointDescrip->rxBuffer[copyPor], wasRead); + copyPor += length; + break; + } + else + { + firstPart = copyUnr - copyPor; + memcpy(buffer, &vcpPointDescrip->rxBuffer[copyPor], firstPart); + buffer += firstPart; + length -= firstPart; + copyUnr = vcpPointDescrip->rxBufferLength; + copyPor = 0; + } + } + } while(1); + + vcpPointDescrip->service.rxPointOfRead = copyPor; + vcpPointDescrip->service.rxPointOfWrite = copyPow; + vcpControl.rxUnusedRemaining = copyUnr; + + vcpEnableReadPipe(); + wasRead += firstPart; + + return wasRead; +} + +/**************************************************************************//** +\brief Checks the status of tx buffer. + +\param[in] descriptor - pointer to HAL_UsartDescriptor_t structure; +\return -1 - bad descriptor, no tx buffer; \n + 1 - tx buffer is empty; \n + 0 - tx buffer is not empty; +******************************************************************************/ +int VCP_IsTxEmpty(HAL_UsartDescriptor_t *descriptor) +{ + HalUsartService_t *halUsartControl; + uint16_t copyPow; + uint16_t copyPor; + + if (NULL == descriptor) + return -1; + + if (vcpPointDescrip != descriptor) + return -1; + + halUsartControl = &descriptor->service; + copyPow = halUsartControl->txPointOfWrite; + copyPor = halUsartControl->txPointOfRead; + + if (copyPow == copyPor) + return 1; + else + return 0; +} + +// eof vcpVirtualUart.c -- cgit v1.2.3