#include "usb_cdc.h" #include /** * Send_Encapsulated_Command * * Nothing to do other than unloading the data sent in the data stage. */ bool USB_CDC::ClassRequest::send_encapsulated_command(const USB::SetupBuffer &buf){ if((buf.bmRequestType == USB::SetupBuffer::OUT_CL_INTERFACE) && (buf.wValue == 0) && (buf.wLength <= sizeof(LineCoding))){ parent.usb.ep0_rx( &(set_line_coding_complete.new_value), buf.wLength, set_line_coding_complete); return true; } return false; } /** * Get_Encapsulated_Command * * Return a zero-length packet */ bool USB_CDC::ClassRequest::get_encapsulated_command(const USB::SetupBuffer &buf){ if((buf.bmRequestType == USB::SetupBuffer::IN_CL_INTERFACE) && (buf.wValue == 0)){ parent.usb.ep0_tx(NULL, 0); // Send ZLP return true; } return false; } void USB_CDC::ClassRequest::SetLineCodingComplete::operator()(){ old_value = new_value; } USB_CDC::ClassRequest::SetLineCodingComplete::SetLineCodingComplete(LineCoding &old) : old_value(old){ } USB_CDC::ClassRequest::SetLineCodingComplete::~SetLineCodingComplete(){} /** * Set_Line_Coding * * Unload the line coding structure (7 bytes) sent in the data stage. * Apply this setting to the UART * Flush the communication buffer * * Line Coding Structure (7 bytes) * 0-3 dwDTERate Data terminal rate (baudrate), in bits per second (LSB first) * 4 bCharFormat Stop bits: 0 - 1 Stop bit, 1 - 1.5 Stop bits, 2 - 2 Stop bits * 5 bParityType Parity: 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space * 6 bDataBits Data bits: 5, 6, 7, 8, 16 */ bool USB_CDC::ClassRequest::set_line_coding(const USB::SetupBuffer &buf){ if((buf.bmRequestType == USB::SetupBuffer::OUT_CL_INTERFACE) && (buf.wValue == 0) && (buf.wLength == sizeof(LineCoding))){ parent.usb.ep0_rx( &(set_line_coding_complete.new_value), buf.wLength, set_line_coding_complete); return true; } return false; } /** * Get_Line_Coding * * Return the line coding structure */ bool USB_CDC::ClassRequest::get_line_coding(const USB::SetupBuffer &buf){ if((buf.bmRequestType == USB::SetupBuffer::IN_CL_INTERFACE) && (buf.wValue == 0) && (buf.wLength == sizeof(LineCoding))){ parent.usb.ep0_tx(&(parent.line_coding), buf.wLength); return true; } return false; } /** * Set_ControlLine_State * * Set/reset RTS/DTR according to wValue * wValue * bit 1 RTS * bit 0 DTR */ bool USB_CDC::ClassRequest::set_control_line_state(const USB::SetupBuffer &buf){ if((buf.bmRequestType == USB::SetupBuffer::OUT_CL_INTERFACE) && (buf.wLength == 0)){ //set_line_state(usb_setup_buf.wValue.c[LSB] & (CDC_RTS | CDC_DTR)); return true; } return false; } /** * Send_Break * * Send break from UART TX port, for wValue (msec) duration. * wValue * 0xFFFF: continuous break * 0x0000: stop break */ bool USB_CDC::ClassRequest::send_break(const USB::SetupBuffer &buf){ if ((buf.bmRequestType == USB::SetupBuffer::OUT_CL_INTERFACE) && (buf.wLength == 0)){ parent.send_break(buf.wValue); return true; } return false; } USB_CDC::ClassRequest::ClassRequest(USB_CDC &usb_cdc) : parent(usb_cdc), set_line_coding_complete(usb_cdc.line_coding) { } USB_CDC::ClassRequest::~ClassRequest(){} bool USB_CDC::ClassRequest::handle(const USB::SetupBuffer &buf){ switch(buf.bRequest){ case SEND_ENCAPSULATED_COMMAND: return send_encapsulated_command(buf); case GET_ENCAPSULATED_RESPONSE: return get_encapsulated_command(buf); case SET_LINE_CODING: return set_line_coding(buf); case GET_LINE_CODING: return get_line_coding(buf); case SET_CONTROL_LINE_STATE: return set_control_line_state(buf); case SEND_BREAK: return send_break(buf); } return false; } void USB_CDC::handle_ctl(){ Uint8 buf_res_available[] = { 0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // ResponseAvailable usb.write(ep_in_ctl, buf_res_available, sizeof(buf_res_available)); Uint8 buf_state[] = { 0xA1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00}; // SerialState usb.write(ep_in_ctl, buf_state, sizeof(buf_state)); } unsigned int USB_CDC::transmit(const char *buf, const unsigned int &buf_size){ return usb.write(ep_in_data, buf, buf_size); } unsigned int USB_CDC::receive(char *buf, const unsigned int &buf_size){ return usb.read(ep_out_data, buf, buf_size); } USB_CDC::USB_CDC( USB &target, const Uint8 &ep_in_ctl_index, const Uint8 &ep_in_data_index, const Uint8 &ep_out_data_index) : MinimalIO(), usb(target), line_coding(), class_request_handler(*this), ep_in_ctl(ep_in_ctl_index), ep_in_data(ep_in_data_index), ep_out_data(ep_out_data_index) { Uint32 baudrate(115200u); std::memcpy(line_coding.baudrate, &baudrate, sizeof(line_coding.baudrate)); line_coding.stopbit = 0; line_coding.parity = 0; line_coding.databit = 8; } USB_CDC::~USB_CDC(){ }