summaryrefslogtreecommitdiff
path: root/at91lib/usb/device/composite/CDCDFunctionDriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'at91lib/usb/device/composite/CDCDFunctionDriver.c')
-rw-r--r--at91lib/usb/device/composite/CDCDFunctionDriver.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/at91lib/usb/device/composite/CDCDFunctionDriver.c b/at91lib/usb/device/composite/CDCDFunctionDriver.c
new file mode 100644
index 0000000..a68f5be
--- /dev/null
+++ b/at91lib/usb/device/composite/CDCDFunctionDriver.c
@@ -0,0 +1,346 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+#if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+// GENERAL
+#include <utility/trace.h>
+#include <utility/assert.h>
+// USB
+#include <usb/device/core/USBD.h>
+// CDC
+#include <usb/common/cdc/CDCLineCoding.h>
+#include <usb/common/cdc/CDCGenericRequest.h>
+#include <usb/common/cdc/CDCSetControlLineStateRequest.h>
+
+#include "CDCDFunctionDriver.h"
+#include "CDCDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+/// Number of serial ports supported
+#if defined(usb_CDCCDC)
+#define CDCD_PORT_NUM 2
+#else
+#define CDCD_PORT_NUM 1
+#endif
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+/// CDC Serial port struct
+typedef struct {
+
+ CDCLineCoding lineCoding;
+ unsigned char isCarrierActivated;
+ unsigned char epDataIn;
+ unsigned char epDataOut;
+ unsigned short serialState;
+
+} CDCDSerialPort;
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// CDCDSerialPort instance
+static CDCDSerialPort cdcdSerial[CDCD_PORT_NUM];
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Callback function which should be invoked after the data of a
+/// SetLineCoding request has been retrieved. Sends a zero-length packet
+/// to the host for acknowledging the request.
+//-----------------------------------------------------------------------------
+static void CDCD_SetLineCodingCallback()
+{
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Return the port index that host send this request for.
+//-----------------------------------------------------------------------------
+static char CDCD_GetSerialPort(const USBGenericRequest *request)
+{
+ if (request->wIndex == CDCD_Descriptors_INTERFACENUM0 + 1) return 0;
+ #if CDCD_PORT_NUM > 1
+ else if (request->wIndex == CDCD_Descriptors_INTERFACENUM1 + 1) return 1;
+ #endif
+ return 0xFF;
+}
+
+//-----------------------------------------------------------------------------
+/// Receives new line coding information from the USB host.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+static void CDCD_SetLineCoding(const USBGenericRequest *request)
+{
+ unsigned char serial;
+ serial = CDCD_GetSerialPort(request);
+
+ TRACE_INFO_WP("sLineCoding_%d ", serial);
+
+ USBD_Read(0,
+ (void *) &(cdcdSerial[serial].lineCoding),
+ sizeof(CDCLineCoding),
+ (TransferCallback) CDCD_SetLineCodingCallback,
+ 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Sends the current line coding information to the host through Control
+/// endpoint 0.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+static void CDCD_GetLineCoding(const USBGenericRequest *request)
+{
+ unsigned char serial;
+ serial = CDCD_GetSerialPort(request);
+
+ TRACE_INFO_WP("gLineCoding_%d ", serial);
+
+ USBD_Write(0,
+ (void *) &(cdcdSerial[serial].lineCoding),
+ sizeof(CDCLineCoding),
+ 0,
+ 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Changes the state of the serial driver according to the information
+/// sent by the host via a SetControlLineState request, and acknowledges
+/// the request with a zero-length packet.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \param activateCarrier The active carrier state to set.
+/// \param isDTEPresent The DTE status.
+//-----------------------------------------------------------------------------
+static void CDCD_SetControlLineState(const USBGenericRequest *request,
+ unsigned char activateCarrier,
+ unsigned char isDTEPresent)
+{
+ unsigned char serial;
+ serial = CDCD_GetSerialPort(request);
+
+ TRACE_INFO_WP(
+ "sControlLineState_%d(%d, %d) ",
+ serial,
+ activateCarrier,
+ isDTEPresent);
+
+ cdcdSerial[serial].isCarrierActivated = activateCarrier;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device CDC serial function driver.
+//-----------------------------------------------------------------------------
+void CDCDFunctionDriver_Initialize()
+{
+ unsigned char serial;
+
+ TRACE_INFO("CDCDFunctionDriver_Initialize\n\r");
+
+ for (serial = 0; serial < CDCD_PORT_NUM; serial ++) {
+
+ CDCDSerialPort * pSerial = &cdcdSerial[serial];
+
+ // Initialize Abstract Control Model attributes
+ CDCLineCoding_Initialize(&(pSerial->lineCoding),
+ 115200,
+ CDCLineCoding_ONESTOPBIT,
+ CDCLineCoding_NOPARITY,
+ 8);
+ pSerial->isCarrierActivated = 0;
+ pSerial->serialState = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Handles CDC/ACM-specific USB requests sent by the host
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 0 if the request is Unsupported, 1 if the request handled.
+//-----------------------------------------------------------------------------
+unsigned char CDCDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request)
+{
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case CDCGenericRequest_SETLINECODING:
+
+ CDCD_SetLineCoding(request);
+ break;
+
+ case CDCGenericRequest_GETLINECODING:
+
+ CDCD_GetLineCoding(request);
+ break;
+
+ case CDCGenericRequest_SETCONTROLLINESTATE:
+
+ CDCD_SetControlLineState(request,
+ CDCSetControlLineStateRequest_ActivateCarrier(request),
+ CDCSetControlLineStateRequest_IsDtePresent(request));
+
+ break;
+
+ // Unsupported request
+ default:
+ return 0;
+
+ }
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+/// Receives data from the host through the virtual COM port created by
+/// the CDC function serial driver. This function behaves like <USBD_Read>.
+/// \param Port Port index to receive.
+/// \param Pointer to the data buffer to send.
+/// \param Size of the data buffer in bytes.
+/// \param callback Optional callback function to invoke when the transfer
+/// finishes.
+/// \param argument Optional argument to the callback function.
+/// \return <USBD_STATUS_SUCCESS> if the read operation started normally;
+/// otherwise, the corresponding error code.
+//-----------------------------------------------------------------------------
+unsigned char CDCDSerialDriver_Read(unsigned char port,
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ unsigned char ep = CDCD_Descriptors_DATAOUT0;
+
+ #if CDCD_PORT_NUM > 1
+ ep = (port == 0) ?
+ CDCD_Descriptors_DATAOUT0 : CDCD_Descriptors_DATAOUT1;
+ #endif
+
+ return USBD_Read(ep,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// Sends a data buffer through the virtual COM port created by the CDC
+/// function serial driver. This function behaves exactly like <USBD_Write>.
+/// \param port Port index to receive.
+/// \param data - Pointer to the data buffer to send.
+/// \param size - Size of the data buffer in bytes.
+/// \param callback - Optional callback function to invoke when the transfer
+/// finishes.
+/// \param argument - Optional argument to the callback function.
+/// \return <USBD_STATUS_SUCCESS> if the write operation started normally;
+/// otherwise, the corresponding error code.
+//-----------------------------------------------------------------------------
+unsigned char CDCDSerialDriver_Write(unsigned char port,
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ unsigned char ep = CDCD_Descriptors_DATAIN0;
+
+ #if CDCD_PORT_NUM > 1
+ ep = (port == 0) ?
+ CDCD_Descriptors_DATAIN0 : CDCD_Descriptors_DATAIN1;
+ #endif
+
+ return USBD_Write(ep,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current status of the RS-232 line.
+/// \param port The port number that checked.
+//------------------------------------------------------------------------------
+unsigned short CDCDSerialDriver_GetSerialState(unsigned char port)
+{
+ return cdcdSerial[port].serialState;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current serial state of the device to the given value.
+/// \param port The port number that the port state should be changed.
+/// \param serialState New device state.
+//------------------------------------------------------------------------------
+void CDCDSerialDriver_SetSerialState(unsigned char port,
+ unsigned short serialState)
+{
+ CDCDSerialPort * pPort;
+ unsigned char ep = 0;
+
+ ASSERT((serialState & 0xFF80) == 0,
+ "CDCDSerialDriver_SetSerialState: Bits D7-D15 are reserved!\n\r");
+
+ // If new state is different from previous one, send a notification to the
+ // host
+ pPort = &cdcdSerial[port];
+ if (pPort->serialState != serialState) {
+
+ #if CDCD_PORT_NUM > 1
+ ep = (port == 0) ?
+ CDCD_Descriptors_NOTIFICATION0 : CDCD_Descriptors_NOTIFICATION1;
+ #endif
+
+ pPort->serialState = serialState;
+ USBD_Write(ep,
+ &(pPort->serialState),
+ 2,
+ 0,
+ 0);
+
+ // Reset one-time flags
+ pPort->serialState &= ~(CDCD_STATE_OVERRUN
+ | CDCD_STATE_PARITY
+ | CDCD_STATE_FRAMING
+ | CDCD_STATE_RINGSIGNAL
+ | CDCD_STATE_BREAK);
+ }
+}
+#endif // (CDC defined)
+
personal git repositories of Harald Welte. Your mileage may vary