1 /* 2 * Copyright (c) 2007-2008 by Michael Lotz 3 * Heavily based on the original usb_serial driver which is: 4 * 5 * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li> 6 * Distributed under the terms of the MIT License. 7 */ 8 #include "FTDI.h" 9 #include "FTDIRegs.h" 10 11 FTDIDevice::FTDIDevice(usb_device device, uint16 vendorID, uint16 productID, 12 const char *description) 13 : SerialDevice(device, vendorID, productID, description), 14 fHeaderLength(0), 15 fStatusMSR(0), 16 fStatusLSR(0) 17 { 18 } 19 20 21 status_t 22 FTDIDevice::AddDevice(const usb_configuration_info *config) 23 { 24 TRACE_FUNCALLS("> FTDIDevice::AddDevice(%08x, %08x)\n", this, config); 25 status_t status = ENODEV; 26 if (config->interface_count > 0) { 27 int32 pipesSet = 0; 28 usb_interface_info *interface = config->interface[0].active; 29 for (size_t i = 0; i < interface->endpoint_count; i++) { 30 usb_endpoint_info *endpoint = &interface->endpoint[i]; 31 if (endpoint->descr->attributes == USB_EP_ATTR_BULK) { 32 if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { 33 SetReadPipe(endpoint->handle); 34 if (++pipesSet >= 3) 35 break; 36 } else { 37 if (endpoint->descr->endpoint_address) { 38 SetControlPipe(endpoint->handle); 39 SetWritePipe(endpoint->handle); 40 pipesSet += 2; 41 if (pipesSet >= 3) 42 break; 43 } 44 } 45 } 46 } 47 48 if (pipesSet >= 3) { 49 if (ProductID() == PRODUCT_FTDI_8U100AX) 50 fHeaderLength = 1; 51 else 52 fHeaderLength = 0; 53 54 status = B_OK; 55 } 56 } 57 58 TRACE_FUNCRET("< FTDIDevice::AddDevice() returns: 0x%08x\n", status); 59 return status; 60 } 61 62 63 status_t 64 FTDIDevice::ResetDevice() 65 { 66 TRACE_FUNCALLS("> FTDIDevice::ResetDevice(0x%08x)\n", this); 67 68 size_t length = 0; 69 status_t status = gUSBModule->send_request(Device(), 70 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 71 FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, 72 FTDI_PIT_DEFAULT, 0, NULL, &length); 73 74 TRACE_FUNCRET("< FTDIDevice::ResetDevice() returns:%08x\n", status); 75 return status; 76 } 77 78 79 status_t 80 FTDIDevice::SetLineCoding(usb_serial_line_coding *lineCoding) 81 { 82 TRACE_FUNCALLS("> FTDIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n", 83 this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity, 84 lineCoding->databits); 85 86 int32 rate = 0; 87 if (ProductID() == PRODUCT_FTDI_8U100AX) { 88 switch (lineCoding->speed) { 89 case 300: rate = ftdi_sio_b300; break; 90 case 600: rate = ftdi_sio_b600; break; 91 case 1200: rate = ftdi_sio_b1200; break; 92 case 2400: rate = ftdi_sio_b2400; break; 93 case 4800: rate = ftdi_sio_b4800; break; 94 case 9600: rate = ftdi_sio_b9600; break; 95 case 19200: rate = ftdi_sio_b19200; break; 96 case 38400: rate = ftdi_sio_b38400; break; 97 case 57600: rate = ftdi_sio_b57600; break; 98 case 115200: rate = ftdi_sio_b115200; break; 99 default: 100 rate = ftdi_sio_b19200; 101 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is " 102 "not supported by this hardware. Defaulted to %d\n", 103 lineCoding->speed, rate); 104 break; 105 } 106 } else { 107 switch (lineCoding->speed) { 108 case 300: rate = ftdi_8u232am_b300; break; 109 case 600: rate = ftdi_8u232am_b600; break; 110 case 1200: rate = ftdi_8u232am_b1200; break; 111 case 2400: rate = ftdi_8u232am_b2400; break; 112 case 4800: rate = ftdi_8u232am_b4800; break; 113 case 9600: rate = ftdi_8u232am_b9600; break; 114 case 19200: rate = ftdi_8u232am_b19200; break; 115 case 38400: rate = ftdi_8u232am_b38400; break; 116 case 57600: rate = ftdi_8u232am_b57600; break; 117 case 115200: rate = ftdi_8u232am_b115200; break; 118 case 230400: rate = ftdi_8u232am_b230400; break; 119 case 460800: rate = ftdi_8u232am_b460800; break; 120 case 921600: rate = ftdi_8u232am_b921600; break; 121 default: 122 rate = ftdi_sio_b19200; 123 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is " 124 "not supported by this hardware. Defaulted to %d\n", 125 lineCoding->speed, rate); 126 break; 127 } 128 } 129 130 size_t length = 0; 131 status_t status = gUSBModule->send_request(Device(), 132 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 133 FTDI_SIO_SET_BAUD_RATE, rate, 134 FTDI_PIT_DEFAULT, 0, NULL, &length); 135 if (status != B_OK) 136 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): datarate set request failed: 0x%08x\n", status); 137 138 int32 data = 0; 139 switch (lineCoding->stopbits) { 140 case LC_STOP_BIT_2: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break; 141 case LC_STOP_BIT_1: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break; 142 default: 143 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong stopbits param: %d\n", 144 lineCoding->stopbits); 145 break; 146 } 147 148 switch (lineCoding->parity) { 149 case LC_PARITY_NONE: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break; 150 case LC_PARITY_EVEN: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break; 151 case LC_PARITY_ODD: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break; 152 default: 153 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong parity param: %d\n", 154 lineCoding->parity); 155 break; 156 } 157 158 switch (lineCoding->databits) { 159 case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break; 160 case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break; 161 default: 162 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong databits param: %d\n", 163 lineCoding->databits); 164 break; 165 } 166 167 length = 0; 168 status = gUSBModule->send_request(Device(), 169 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 170 FTDI_SIO_SET_DATA, data, 171 FTDI_PIT_DEFAULT, 0, NULL, &length); 172 if (status != B_OK) 173 TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): data set request failed: %08x\n", status); 174 175 TRACE_FUNCRET("< FTDIDevice::SetLineCoding() returns: 0x%08x\n", status); 176 return status; 177 } 178 179 180 status_t 181 FTDIDevice::SetControlLineState(uint16 state) 182 { 183 TRACE_FUNCALLS("> FTDIDevice::SetControlLineState(0x%08x, 0x%04x)\n", this, state); 184 185 int32 control; 186 control = (state & CLS_LINE_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; 187 control |= (state & CLS_LINE_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; 188 189 size_t length = 0; 190 status_t status = gUSBModule->send_request(Device(), 191 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 192 FTDI_SIO_MODEM_CTRL, control, 193 FTDI_PIT_DEFAULT, 0, NULL, &length); 194 195 if (status != B_OK) 196 TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status); 197 198 TRACE_FUNCRET("< FTDIDevice::SetControlLineState() returns: 0x%08x\n", status); 199 return status; 200 } 201 202 203 void 204 FTDIDevice::OnRead(char **buffer, size_t *numBytes) 205 { 206 fStatusMSR = FTDI_GET_MSR(*buffer); 207 fStatusLSR = FTDI_GET_LSR(*buffer); 208 TRACE("FTDIDevice::OnRead(): MSR: 0x%02x LSR: 0x%02x\n", fStatusMSR, fStatusLSR); 209 *buffer += 2; 210 *numBytes -= 2; 211 } 212 213 214 void 215 FTDIDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) 216 { 217 char *writeBuffer = WriteBuffer(); 218 if (fHeaderLength > 0) { 219 if (*numBytes >= WriteBufferSize() - fHeaderLength) 220 *numBytes = *packetBytes = WriteBufferSize() - fHeaderLength; 221 222 *writeBuffer = FTDI_OUT_TAG(*numBytes, FTDI_PIT_DEFAULT); 223 } 224 225 memcpy(writeBuffer + fHeaderLength, buffer, *packetBytes); 226 *packetBytes += fHeaderLength; 227 } 228