Warning, cross-references for /kernel/drivers/usb/ftdi.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <drivers/usb/usb.h>
0019 #include <drivers/usb/uhci.h>
0020 #include <drivers/usb/ftdi.h>
0021 #include <arch/i386.h>
0022 #include <util/printf.h>
0023 #include <kernel.h>
0024
0025 #define DEBUG_FTDI
0026
0027 #ifdef DEBUG_FTDI
0028 #define DLOG(fmt,...) DLOG_PREFIX("ftdi",fmt,##__VA_ARGS__)
0029 #else
0030 #define DLOG(fmt,...) ;
0031 #endif
0032
0033
0034 #define FTDI_BASE_CLOCK 48000000
0035
0036 static USB_DEVICE_INFO ftdi_dev;
0037 static uint8_t in_ept = 0, out_ept = 0;
0038
0039 bool usb_ftdi_driver_init (void);
0040 void usb_ftdi_putc (char);
0041 char usb_ftdi_getc (void);
0042 int usb_ftdi_write (unsigned char *, uint32_t);
0043 int usb_ftdi_read (unsigned char *, uint32_t);
0044
0045
0046
0047
0048
0049
0050 static int
0051 ftdi_reset (USB_DEVICE_INFO * dev, uint16_t port)
0052 {
0053 USB_DEV_REQ req;
0054 req.bmRequestType = 0x40;
0055 req.bRequest = USB_FTDI_RESET;
0056
0057
0058
0059
0060 req.wValue = 0;
0061 req.wIndex = port;
0062 req.wLength = 0;
0063
0064 return usb_control_transfer (dev, (addr_t) & req,
0065 sizeof (USB_DEV_REQ), 0, 0);
0066 }
0067
0068
0069
0070 static uint32_t
0071 ftdi_baud_base_to_divisor (uint32_t baud, uint32_t base)
0072 {
0073 static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
0074 uint32_t divisor;
0075
0076 int divisor3 = base / 2 / baud;
0077 divisor = divisor3 >> 3;
0078 divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14;
0079
0080 if (divisor == 1)
0081 divisor = 0;
0082 else if (divisor == 0x4001)
0083 divisor = 1;
0084 return divisor;
0085 }
0086
0087 static int
0088 ftdi_set_baud (USB_DEVICE_INFO * dev, uint32_t baud, uint16_t port)
0089 {
0090 USB_DEV_REQ req;
0091 uint32_t divisor = ftdi_baud_base_to_divisor (baud, FTDI_BASE_CLOCK);
0092
0093 req.bmRequestType = 0x40;
0094 req.bRequest = USB_FTDI_SET_BAUD_RATE;
0095 req.wValue = divisor;
0096 req.wIndex = port;
0097 req.wLength = 0;
0098
0099 return usb_control_transfer (dev, (addr_t) & req,
0100 sizeof (USB_DEV_REQ), 0, 0);
0101 }
0102
0103
0104 static int
0105 ftdi_set_data (
0106 USB_DEVICE_INFO * dev,
0107 uint8_t bits,
0108 uint8_t parity,
0109 uint8_t stb,
0110 uint8_t tx,
0111 uint16_t port)
0112 {
0113 USB_DEV_REQ req;
0114 uint16_t dc = (tx & 0x1) << 14 |
0115 (stb & 0x7) << 11 | (parity & 0x7) << 8 | bits;
0116
0117 req.bmRequestType = 0x40;
0118 req.bRequest = USB_FTDI_SET_DATA;
0119 req.wValue = dc;
0120 req.wIndex = port;
0121 req.wLength = 0;
0122
0123 return usb_control_transfer (dev, (addr_t) & req,
0124 sizeof (USB_DEV_REQ), 0, 0);
0125 }
0126
0127 static uint16_t
0128 ftdi_modem_status (USB_DEVICE_INFO * dev, uint16_t port)
0129 {
0130 USB_DEV_REQ req;
0131 uint16_t status;
0132
0133 req.bmRequestType = 0xC0;
0134 req.bRequest = USB_FTDI_GET_MODEM_STATUS;
0135 req.wValue = 0;
0136 req.wIndex = port;
0137 req.wLength = 2;
0138
0139 if (usb_control_transfer (dev, (addr_t) & req,
0140 sizeof (USB_DEV_REQ), (addr_t) & status, req.wLength)) {
0141 DLOG ("Get modem status failed");
0142 return 0xFFFF;
0143 }
0144
0145 return status;
0146 }
0147
0148 static int
0149 ftdi_set_flow_ctl (USB_DEVICE_INFO * dev, uint16_t port, uint8_t ctrl)
0150 {
0151 USB_DEV_REQ req;
0152
0153 req.bmRequestType = 0x40;
0154 req.bRequest = USB_FTDI_SET_FLOW_CTRL;
0155 req.wValue = 0;
0156 req.wIndex = (ctrl << 8) + port;
0157 req.wLength = 0;
0158
0159 return usb_control_transfer (dev, (addr_t) & req,
0160 sizeof (USB_DEV_REQ), 0, 0);
0161 }
0162
0163
0164 static int
0165 ftdi_set_latency (USB_DEVICE_INFO * dev, uint16_t port, uint8_t latency)
0166 {
0167 USB_DEV_REQ req;
0168
0169 req.bmRequestType = 0x40;
0170 req.bRequest = USB_FTDI_SET_LATENCY_TIMER;
0171 req.wValue = latency;
0172 req.wIndex = port;
0173 req.wLength = 0;
0174
0175 return usb_control_transfer (dev, (addr_t) & req,
0176 sizeof (USB_DEV_REQ), 0, 0);
0177 }
0178
0179 static uint8_t
0180 ftdi_get_latency (USB_DEVICE_INFO * dev, uint16_t port)
0181 {
0182 USB_DEV_REQ req;
0183 uint8_t latency = 0;
0184
0185 req.bmRequestType = 0xC0;
0186 req.bRequest = USB_FTDI_GET_LATENCY_TIMER;
0187 req.wValue = 0;
0188 req.wIndex = port;
0189 req.wLength = 1;
0190
0191 if (usb_control_transfer (dev, (addr_t) & req,
0192 sizeof (USB_DEV_REQ), (addr_t) & latency, 1)) {
0193 DLOG ("Getting latency timer failed!");
0194 return 0;
0195 }
0196
0197 return latency;
0198 }
0199
0200 static bool
0201 ftdi_init (USB_DEVICE_INFO *dev, USB_CFG_DESC *cfg, USB_IF_DESC *ifd)
0202 {
0203 uint8_t tmp[50];
0204 int i = 0;
0205 uint16_t mod_stat = 0;
0206 uint8_t latency = 0;
0207 USB_EPT_DESC *ftdiept;
0208
0209 ftdi_dev = *(dev);
0210 memset (tmp, 0, 50);
0211
0212
0213 DLOG ("Parsing FTDI chip endpoints ...");
0214 usb_get_descriptor (dev, USB_TYPE_CFG_DESC, 0, 0, cfg->wTotalLength,
0215 (addr_t)tmp);
0216 for (i = 0; i < cfg->wTotalLength; i += ftdiept->bLength) {
0217 ftdiept = (USB_EPT_DESC *) (tmp + i);
0218 if ((ftdiept->bDescriptorType == USB_TYPE_EPT_DESC) &&
0219 ((ftdiept->bmAttributes & 0x3) == 0x2)) {
0220 DLOG ("Found Bulk Endpoint");
0221 switch (ftdiept->bEndpointAddress & 0x80) {
0222 case 0x80 :
0223 in_ept = ftdiept->bEndpointAddress & 0xF;
0224 DLOG ("IN Endpoint. Address is: 0x%X", in_ept);
0225 break;
0226
0227 case 0x00 :
0228 out_ept = ftdiept->bEndpointAddress & 0xF;
0229 DLOG ("OUT Endpoint. Address is: 0x%X", out_ept);
0230 break;
0231
0232 default :
0233 break;
0234 }
0235 }
0236 }
0237
0238
0239 DLOG ("Resetting FTDI chip ...");
0240 if (ftdi_reset (dev, 0)) {
0241 DLOG ("Chip reset failed!");
0242 return FALSE;
0243 }
0244
0245
0246 DLOG ("Setting baud rate ...");
0247 if (ftdi_set_baud (dev, 38400, 0)) {
0248 DLOG ("Setting baud rate failed!");
0249 return FALSE;
0250 }
0251
0252
0253 DLOG ("Setting data characteristics ...");
0254 if (ftdi_set_data (dev, 8, 0, 0, 0, 0)) {
0255 DLOG ("Setting data characteristics failed!");
0256 return FALSE;
0257 }
0258
0259
0260 DLOG ("Setting latency timer ...");
0261 if (ftdi_set_latency (dev, 0, 16)) {
0262 DLOG ("Setting latency timer failed!");
0263 return FALSE;
0264 }
0265
0266
0267 DLOG ("Getting latency timer ...");
0268 if ((latency = ftdi_get_latency (dev, 0))) {
0269 DLOG ("Current timeout interval is: %d", latency);
0270 }
0271
0272
0273 DLOG ("Setting flow control ...");
0274 if (ftdi_set_flow_ctl (dev, 0, USB_FTDI_NO_FLOW_CTRL)) {
0275 DLOG ("Setting flow control failed!");
0276 return FALSE;
0277 }
0278 #if 1
0279
0280 DLOG ("Getting modem status ...");
0281 if ((mod_stat = ftdi_modem_status (dev, 0)) == 0xFFFF) {
0282 DLOG ("Getting modem status failed!");
0283 return FALSE;
0284 } else {
0285 DLOG ("Modem status is: 0x%X", mod_stat);
0286 }
0287 #endif
0288 return TRUE;
0289 }
0290
0291 static void
0292 ftdi_test (void)
0293 {
0294 DLOG ("FTDI Tests");
0295 char c = 0;
0296
0297 usb_ftdi_putc ('!');
0298
0299 while (c != 0xD) {
0300 c = usb_ftdi_getc ();
0301 DLOG ("Got character : %c", c);
0302 usb_ftdi_putc (c);
0303 }
0304 }
0305
0306 static bool
0307 ftdi_probe (USB_DEVICE_INFO *dev, USB_CFG_DESC *cfg, USB_IF_DESC *ifd)
0308 {
0309 if (dev->devd.idVendor == 0x0403) {
0310 DLOG ("An FTDI chip is detected");
0311
0312 if (dev->devd.idProduct != 0x6001) {
0313 DLOG ("FT232 not found. Product ID is: 0x%X",
0314 dev->devd.idProduct);
0315 return FALSE;
0316 }
0317 } else {
0318 return FALSE;
0319 }
0320
0321 if (!ftdi_init(dev, cfg, ifd)) {
0322 DLOG("Initialization failed!");
0323 return FALSE;
0324 }
0325
0326 DLOG ("FTDI Serial Converter configured");
0327
0328
0329 return TRUE;
0330 }
0331
0332 char
0333 usb_ftdi_getc (void)
0334 {
0335 unsigned char buf[3];
0336 int act_len = 0;
0337
0338 if ((act_len = usb_ftdi_read (buf, 3)) != 3) {
0339 DLOG ("usb_ftdi_read () failed. %d bytes returned.", act_len);
0340 return '\0';
0341 }
0342
0343 return buf[2];
0344 }
0345
0346 void
0347 usb_ftdi_putc (char c)
0348 {
0349 unsigned char buf[2];
0350 int count = 0, buf_size = 0;
0351
0352 #if 0
0353
0354
0355
0356 buf[0] = (1 << 2) | 1;
0357
0358 buf[1] = c;
0359 buf_size = 2;
0360 #else
0361 buf[0] = c;
0362 buf_size = 1;
0363 #endif
0364
0365 if ((count = usb_ftdi_write (buf, buf_size)) != buf_size)
0366 DLOG ("usb_ftdi_putc failed, %d bytes sent", count);
0367 else
0368 DLOG ("usb_ftdi_putc done, %d bytes sent", count);
0369 }
0370
0371 int
0372 usb_ftdi_write (unsigned char * buf, uint32_t len)
0373 {
0374 uint32_t act_len = 0;
0375 int status = 0;
0376
0377 if ((status = usb_bulk_transfer (&ftdi_dev, out_ept, (addr_t) buf,
0378 len, 64, DIR_OUT, &act_len)))
0379 DLOG ("Bulk write failed. Error Code: 0x%X", status);
0380
0381 return act_len;
0382 }
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 int
0412 usb_ftdi_read (unsigned char * buf, uint32_t len)
0413 {
0414 uint32_t act_len = 0;
0415 int status = 0;
0416
0417 if ((status = usb_bulk_transfer (&ftdi_dev, in_ept, (addr_t) buf,
0418 len, 64, DIR_IN, &act_len)))
0419 DLOG ("Bulk read failed. Error Code: 0x%X", status);
0420
0421 return act_len;
0422 }
0423
0424 static USB_DRIVER ftdi_driver = {
0425 .probe = ftdi_probe
0426 };
0427
0428 bool
0429 usb_ftdi_driver_init (void)
0430 {
0431 return usb_register_driver (&ftdi_driver);
0432 }
0433
0434 #include "module/header.h"
0435
0436 static const struct module_ops mod_ops = {
0437 .init = usb_ftdi_driver_init
0438 };
0439
0440 DEF_MODULE (usb___ftdi, "USB FTDI driver", &mod_ops, {"usb"});
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451