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