Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBCDC.cpp Source File

USBCDC.cpp

00001 /* Copyright (c) 2010-2011 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #include <cstdint>
00020 #include <cstdio>
00021 #include <cstring>
00022 
00023 #include "USBCDC.h"
00024 
00025 // static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};
00026 
00027 #define iprintf(...) do { } while (0)
00028 
00029 // #define DEFAULT_CONFIGURATION (1)
00030 
00031 // #define CDC_SET_LINE_CODING        0x20
00032 // #define CDC_GET_LINE_CODING        0x21
00033 // #define CDC_SET_CONTROL_LINE_STATE 0x22
00034 
00035 // #define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK
00036 
00037 USBCDC::USBCDC(USB *u) {
00038     usb = u;
00039 
00040     CDC_iad = {
00041         DL_INTERFACE_ASSOCIATION,
00042         DT_INTERFACE_ASSOCIATION,
00043         0,                          // bFirstInterface - filled out later
00044         2,                          // bInterfaceCount - contiguous interfaces associated with this function
00045         UC_COMM,                    // bFunctionClass
00046         USB_CDC_SUBCLASS_ACM,       // bFunctionSubClass
00047         USB_CDC_PROTOCOL_ITU_V250,  // bFunctionProtocol
00048         0,                          // iFunction
00049     };
00050     CDC_if = {
00051         DL_INTERFACE,               // bLength
00052         DT_INTERFACE,               // bDescType
00053         0,                          // bInterfaceNumber: filled out during addInterface()
00054         0,                          // bAlternateSetting
00055         1,                          // bNumEndpoints
00056         UC_COMM,                    // bInterfaceClass
00057         USB_CDC_SUBCLASS_ACM,       // bInterfaceSubClass
00058         USB_CDC_PROTOCOL_ITU_V250,  // bInterfaceProtocol
00059         0,                          // iInterface
00060         0, 0, 0,                    // dummy padding
00061         this,                       // callback
00062     };
00063     CDC_intep = {
00064         DL_ENDPOINT,            // bLength
00065         DT_ENDPOINT,            // bDescType
00066         EP_DIR_IN,              // bEndpointAddress: we provide direction, address is filled in by addEndpoint()
00067         EA_INTERRUPT,           // bmAttributes
00068         8,                      // wMaxPacketSize
00069         16,                     // bInterval
00070         0,                      // dummy padding
00071         this,                   // endpoint callback
00072     };
00073     CDC_header = {
00074         USB_CDC_LENGTH_HEADER,  // bLength
00075         DT_CDC_DESCRIPTOR,      // bDescType
00076         USB_CDC_SUBTYPE_HEADER, // bDescSubType
00077         0x0110,                 // bcdCDC
00078     };
00079     CDC_callmgmt = {
00080         USB_CDC_LENGTH_CALLMGMT,            // bLength
00081         DT_CDC_DESCRIPTOR,                  // bDescType
00082         USB_CDC_SUBTYPE_CALL_MANAGEMENT,    // bDescSubType
00083         USB_CDC_CALLMGMT_CAP_CALLMGMT | USB_CDC_CALLMGMT_CAP_DATAINTF,  // bmCapabilities
00084         0,                      // bDataInterface: filled in later
00085     };
00086     CDC_acm = {
00087         USB_CDC_LENGTH_ACM,     // bLength
00088         DT_CDC_DESCRIPTOR,      // bDescType
00089         USB_CDC_SUBTYPE_ACM,    // bDescSubType
00090         USB_CDC_ACM_CAP_LINE | USB_CDC_ACM_CAP_BRK, // bmCapabilities
00091     };
00092     CDC_union = {
00093         USB_CDC_LENGTH_UNION,   // bLength
00094         DT_CDC_DESCRIPTOR,      // bDescType
00095         USB_CDC_SUBTYPE_UNION,  // bDescSubType
00096         0,                      // bMasterInterface
00097         0,                      // bSlaveInterface0
00098     };
00099     CDC_slaveif = {
00100         DL_INTERFACE,           // bLength
00101         DT_INTERFACE,           // bDescType
00102         0,                      // bInterfaceNumber: filled out during addInterface()
00103         0,                      // bAlternateSetting
00104         2,                      // bNumEndpoints
00105         UC_CDC_DATA,            // bInterfaceClass
00106         0,                      // bInterfaceSubClass
00107         0,                      // bInterfaceProtocol
00108         0,                      // iInterface
00109         0, 0, 0,                // dummy padding
00110         this,                   // callback
00111     };
00112     CDC_BulkIn = {
00113         DL_ENDPOINT,            // bLength
00114         DT_ENDPOINT,            // bDescType
00115         EP_DIR_IN,              // bEndpointAddress: we provide direction, address is filled in by addEndpoint()
00116         EA_BULK,                // bmAttributes
00117         MAX_PACKET_SIZE_EPBULK, // wMaxPacketSize
00118         1,                      // bInterval
00119         0,                      // dummy padding
00120         this,                   // endpoint callback
00121     };
00122     CDC_BulkOut = {
00123         DL_ENDPOINT,            // bLength
00124         DT_ENDPOINT,            // bDescType
00125         EP_DIR_OUT,             // bEndpointAddress: we provide direction, address is filled in by addEndpoint()
00126         EA_BULK,                // bmAttributes
00127         MAX_PACKET_SIZE_EPBULK, // wMaxPacketSize
00128         1,                      // bInterval
00129         0,                      // dummy padding
00130         this,                   // endpoint callback
00131     };
00132 
00133     usbdesc_string_l(16) s = usbstring("Smoothie Serial");
00134     memcpy(&CDC_string, &s, sizeof(CDC_string));
00135 
00136     usb->addDescriptor(&CDC_iad);
00137     uint8_t IfAddr =
00138         usb->addInterface(&CDC_if);
00139     usb->addDescriptor(&CDC_header);
00140     usb->addDescriptor(&CDC_callmgmt);
00141     usb->addDescriptor(&CDC_acm);
00142     usb->addDescriptor(&CDC_union);
00143     usb->addEndpoint(&CDC_intep);
00144     uint8_t slaveIfAddr =
00145         usb->addInterface(&CDC_slaveif);
00146     usb->addEndpoint(&CDC_BulkOut);
00147     usb->addEndpoint(&CDC_BulkIn);
00148 
00149     CDC_if.iInterface = usb->addString(&CDC_string);
00150 
00151     CDC_iad.bFirstInterface     = IfAddr;
00152     CDC_iad.iFunction           = CDC_if.iInterface;
00153     CDC_union.bMasterInterface  = IfAddr;
00154     CDC_union.bSlaveInterface0  = slaveIfAddr;
00155     CDC_callmgmt.bDataInterface = slaveIfAddr;
00156 
00157     cdc_line_coding.dwDTERate = 9600;
00158     cdc_line_coding.bCharFormat = 0;
00159     cdc_line_coding.bParityType = 0;
00160     cdc_line_coding.bDataBits   = 8;
00161 }
00162 
00163 /* Called in ISR context */
00164 bool USBCDC::USBEvent_Request(CONTROL_TRANSFER &transfer) {
00165 
00166     /* Process class-specific requests */
00167 
00168     if (transfer.setup.bmRequestType.Type == CLASS_TYPE) {
00169         switch (transfer.setup.bRequest) {
00170             case CDC_GET_LINE_CODING:
00171 //                 iprintf("[CDC]:GET_LINE_ENCODING\n");
00172                 transfer.remaining = 7;
00173                 transfer.ptr = (uint8_t *) &cdc_line_coding;
00174                 transfer.direction = DEVICE_TO_HOST;
00175                 return true;
00176             case CDC_SET_LINE_CODING:
00177 //                 iprintf("[CDC]:SET_LINE_ENCODING\n");
00178                 transfer.remaining = 7;
00179                 transfer.ptr = (uint8_t *) &cdc_line_coding;
00180                 transfer.notify = true;
00181                 transfer.direction = HOST_TO_DEVICE;
00182                 return true;
00183             case CDC_SET_CONTROL_LINE_STATE:
00184                 iprintf("[CDC]:SET_CONTROL_LINE_STATE 0x%02X\n", transfer.setup.wValue);
00185                 if (transfer.setup.wValue & CDC_CLS_DTR)
00186                     on_attach();
00187                 else
00188                     on_detach();
00189                 return true;
00190             default:
00191                 break;
00192         }
00193     }
00194 
00195     return false;
00196 }
00197 
00198 bool USBCDC::USBEvent_RequestComplete(CONTROL_TRANSFER &transfer, uint8_t* buffer, uint32_t length)
00199 {
00200     if (transfer.setup.bmRequestType.Type == CLASS_TYPE)
00201     {
00202         switch (transfer.setup.bRequest)
00203         {
00204             case CDC_SET_LINE_CODING:
00205             {
00206                 iprintf("Got Line Coding:");
00207                 iprintf(" BAUD: %lu ", cdc_line_coding.dwDTERate);
00208                 iprintf(" STOP: ");
00209                     if (cdc_line_coding.bCharFormat == 0) iprintf("1");
00210                     else if (cdc_line_coding.bCharFormat == 1) iprintf("1.5");
00211                     else if (cdc_line_coding.bCharFormat == 2) iprintf("2");
00212                     else iprintf("?");
00213                 iprintf(" PARITY: %d", cdc_line_coding.bParityType);
00214                 iprintf(" DATABITS: %d", cdc_line_coding.bDataBits);
00215 
00216                 iprintf("\n");
00217                 return true;
00218             }
00219         }
00220     }
00221     return false;
00222 }
00223 
00224 bool USBCDC::send(uint8_t * buffer, uint32_t size) {
00225     return usb->writeNB(CDC_BulkIn.bEndpointAddress, buffer, size, CDC_BulkIn.wMaxPacketSize);
00226 }
00227 
00228 bool USBCDC::readEP(uint8_t * buffer, uint32_t * size) {
00229 //     iprintf("USBCDC:readEP 0x%02X\n", CDC_BulkOut.bEndpointAddress);
00230     if (!usb->readEP(CDC_BulkOut.bEndpointAddress, buffer, size, CDC_BulkOut.wMaxPacketSize))
00231     {
00232 //         iprintf("readEP failed\n");
00233         return false;
00234     }
00235 //     iprintf("readEP ok\n");
00236     if (!usb->readStart(CDC_BulkOut.bEndpointAddress, CDC_BulkOut.wMaxPacketSize))
00237     {
00238 //         iprintf("readStart failed\n");
00239         return false;
00240     }
00241 //     iprintf("readStart ok\n");
00242     return true;
00243 }
00244 
00245 bool USBCDC::readEP_NB(uint8_t * buffer, uint32_t * size) {
00246     if (!usb->readEP_NB(CDC_BulkOut.bEndpointAddress, buffer, size, CDC_BulkOut.wMaxPacketSize))
00247         return false;
00248     if (!usb->readStart(CDC_BulkOut.bEndpointAddress, CDC_BulkOut.wMaxPacketSize))
00249         return false;
00250     return true;
00251 }
00252 
00253 void USBCDC::on_attach(void) {}
00254 
00255 void USBCDC::on_detach(void) {}