Norimasa Okamoto / USBLocalFileSystem

Dependencies:   USBDevice

Dependents:   KL46Z-lpc81isp lpcterm2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USB_CDC.cpp Source File

USB_CDC.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 "USB_CDC.h"
00020 
00021 #if (DEBUG2 > 3)
00022 #define CDC_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
00023 #define CDC_DBG_HEX(A,B) while(0);
00024 #else
00025 #define CDC_DBG(...) while(0)
00026 #define CDC_DBG_HEX(A,B) while(0)
00027 #endif
00028 
00029 static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};
00030 
00031 #define CDC_SET_LINE_CODING        0x20
00032 #define CDC_GET_LINE_CODING        0x21
00033 #define CDC_SET_CONTROL_LINE_STATE 0x22
00034 #define CDC_SEND_BREAK             0x23
00035 
00036 #define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK
00037 
00038 USB_CDC::USB_CDC(USBDevice* device) : _device(device), _rx_buf(128)
00039     ,settingsChangedCallback(NULL),controlLineStateChangedCallback(NULL),sendBreakCallback(NULL)
00040 {
00041     CDC_DBG("device=%p", device);
00042 
00043     terminal_connected = false;
00044     //USBDevice::connect();
00045 }
00046 
00047 void USB_CDC::putc(int c)
00048 {
00049     if (terminal_connected) {
00050         uint8_t buf[1];
00051         buf[0] = c;
00052         _device->write(CDC_EPBULK_IN, buf, sizeof(buf), MAX_CDC_REPORT_SIZE);
00053     }
00054 }
00055 
00056 int USB_CDC::getc()
00057 {
00058     uint8_t c = 0;
00059     while (_rx_buf.isEmpty());
00060     _rx_buf.dequeue(&c);
00061     return c;
00062 }
00063 
00064 int USB_CDC::readable()
00065 {
00066     return _rx_buf.available() > 0 ? 1 : 0;
00067 }
00068 
00069 int USB_CDC::writeable()
00070 {
00071     return 1;
00072 }
00073 
00074 bool USB_CDC::send(uint8_t * buffer, uint32_t size) {
00075     return _device->write(CDC_EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE);
00076 }
00077 
00078 bool USB_CDC::readEP(uint8_t * buffer, uint32_t * size) {
00079     if (!_device->readEP(CDC_EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
00080         return false;
00081     if (!_device->readStart(CDC_EPBULK_OUT, MAX_CDC_REPORT_SIZE))
00082         return false;
00083     return true;
00084 }
00085 
00086 bool USB_CDC::readEP_NB(uint8_t * buffer, uint32_t * size) {
00087     if (!_device->readEP_NB(CDC_EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
00088         return false;
00089     if (!_device->readStart(CDC_EPBULK_OUT, MAX_CDC_REPORT_SIZE))
00090         return false;
00091     return true;
00092 }
00093 
00094 bool USB_CDC::Request_callback(CONTROL_TRANSFER* transfer)
00095 {
00096     if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
00097         switch (transfer->setup.bRequest) {
00098             case CDC_SET_LINE_CODING: // 0x20
00099                 transfer->remaining = 7;
00100                 transfer->notify = true;
00101                 terminal_connected = true;
00102                 return true;
00103 
00104             case CDC_GET_LINE_CODING: // x021
00105                 transfer->remaining = 7;
00106                 transfer->ptr = cdc_line_coding;
00107                 transfer->direction = DEVICE_TO_HOST;
00108                 return true;
00109 
00110             case CDC_SET_CONTROL_LINE_STATE: // 0x22
00111                 controlLineStateChanged((transfer->setup.wValue>>1) & 1, (transfer->setup.wValue) & 1);
00112                 terminal_connected = false;
00113                 return true;
00114             
00115             case CDC_SEND_BREAK: // 0x23
00116                 sendBreak(transfer->setup.wValue);
00117                 return true;
00118         }
00119     }
00120     return false;
00121 }
00122 
00123 bool USB_CDC::RequestCompleted_callback(CONTROL_TRANSFER* transfer, uint8_t* buf, int length)
00124 {
00125     CDC_DBG("transer=%p", transfer);
00126     if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
00127         if (transfer->setup.bRequest == CDC_SET_LINE_CODING) {
00128             if (memcmp(cdc_line_coding, buf, 7)) {
00129                 memcpy(cdc_line_coding, buf, 7);
00130 
00131                 int baud = buf[0] + (buf[1] << 8)
00132                          + (buf[2] << 16) + (buf[3] << 24);
00133                 int stop = (buf[4] == 0) ? 1 : 2;
00134                 int bits = buf[6];
00135                 int parity = buf[5];
00136                 lineCodingChanged(baud, bits, parity, stop);
00137                 return true;
00138             }
00139         }
00140     }
00141     CDC_DBG_HEX((uint8_t*)transfer, sizeof(CONTROL_TRANSFER));
00142     return false;           
00143 }
00144 
00145 bool USB_CDC::EPBULK_OUT_callback() // virtual COM to target
00146 {
00147     uint8_t buf[MAX_CDC_REPORT_SIZE];
00148     uint32_t size = 0;
00149     //we read the packet received and put it on the circular buffer
00150     _device->readEP(CDC_EPBULK_OUT, buf, &size, MAX_CDC_REPORT_SIZE);
00151     CDC_DBG("size=%d", size);
00152     for(int i = 0; i < size; i++) {
00153         _rx_buf.queue(buf[i]);
00154     }
00155 
00156     // We reactivate the endpoint to receive next characters
00157     _device->readStart(CDC_EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
00158     return true;
00159 }
00160 
00161 void USB_CDC::lineCodingChanged(int baud, int bits, int parity, int stop)
00162 {
00163     CDC_DBG("baud=%d,bits=%d,parity=%d,stop=%d", baud,bits, parity, stop);
00164     if (settingsChangedCallback) {
00165         settingsChangedCallback(baud, bits, parity, stop);
00166     }
00167 }
00168 
00169 void USB_CDC::controlLineStateChanged(int rts, int dtr)
00170 {
00171     CDC_DBG("rts=%d,dtr=%d", rts, dtr);
00172     if (controlLineStateChangedCallback) {
00173         controlLineStateChangedCallback(rts, dtr);
00174     }
00175 }
00176 
00177 void USB_CDC::sendBreak(uint16_t duration)
00178 {
00179     CDC_DBG("duration=%u", duration)
00180     if (sendBreakCallback) {
00181         sendBreakCallback(duration);
00182     }
00183 }
00184