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 "SerialDevice.h" 9 #include "USB3.h" 10 11 #include "ACM.h" 12 #include "FTDI.h" 13 #include "KLSI.h" 14 #include "Prolific.h" 15 16 SerialDevice::SerialDevice(usb_device device, uint16 vendorID, 17 uint16 productID, const char *description) 18 : fDevice(device), 19 fVendorID(vendorID), 20 fProductID(productID), 21 fDescription(description), 22 fDeviceOpen(false), 23 fDeviceRemoved(false), 24 fControlPipe(0), 25 fReadPipe(0), 26 fWritePipe(0), 27 fBufferArea(-1), 28 fReadBuffer(NULL), 29 fReadBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), 30 fWriteBuffer(NULL), 31 fWriteBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), 32 fInterruptBuffer(NULL), 33 fInterruptBufferSize(16), 34 fDoneRead(-1), 35 fDoneWrite(-1), 36 fControlOut(0), 37 fInputStopped(false), 38 fDeviceThread(-1), 39 fStopDeviceThread(false) 40 { 41 memset(&fTTYFile, 0, sizeof(ttyfile)); 42 memset(&fTTY, 0, sizeof(tty)); 43 } 44 45 46 SerialDevice::~SerialDevice() 47 { 48 Removed(); 49 50 if (fDoneRead >= B_OK) 51 delete_sem(fDoneRead); 52 if (fDoneWrite >= B_OK) 53 delete_sem(fDoneWrite); 54 55 if (fBufferArea >= B_OK) 56 delete_area(fBufferArea); 57 58 mutex_destroy(&fReadLock); 59 mutex_destroy(&fWriteLock); 60 } 61 62 63 status_t 64 SerialDevice::Init() 65 { 66 fDoneRead = create_sem(0, "usb_serial:done_read"); 67 fDoneWrite = create_sem(0, "usb_serial:done_write"); 68 mutex_init(&fReadLock, "usb_serial:read_lock"); 69 mutex_init(&fWriteLock, "usb_serial:write_lock"); 70 71 size_t totalBuffers = fReadBufferSize + fWriteBufferSize + fInterruptBufferSize; 72 fBufferArea = create_area("usb_serial:buffers_area", (void **)&fReadBuffer, 73 B_ANY_KERNEL_ADDRESS, ROUNDUP(totalBuffers, B_PAGE_SIZE), B_CONTIGUOUS, 74 B_READ_AREA | B_WRITE_AREA); 75 76 fWriteBuffer = fReadBuffer + fReadBufferSize; 77 fInterruptBuffer = fWriteBuffer + fWriteBufferSize; 78 return B_OK; 79 } 80 81 82 void 83 SerialDevice::SetControlPipe(usb_pipe handle) 84 { 85 fControlPipe = handle; 86 } 87 88 89 void 90 SerialDevice::SetReadPipe(usb_pipe handle) 91 { 92 fReadPipe = handle; 93 } 94 95 96 void 97 SerialDevice::SetWritePipe(usb_pipe handle) 98 { 99 fWritePipe = handle; 100 } 101 102 103 void 104 SerialDevice::SetModes() 105 { 106 struct termios tios; 107 memcpy(&tios, &fTTY.t, sizeof(struct termios)); 108 uint16 newControl = fControlOut; 109 TRACE_FUNCRES(trace_termios, &tios); 110 111 static uint32 baudRates[] = { 112 0x00000000, //B0 113 0x00000032, //B50 114 0x0000004B, //B75 115 0x0000006E, //B110 116 0x00000086, //B134 117 0x00000096, //B150 118 0x000000C8, //B200 119 0x0000012C, //B300 120 0x00000258, //B600 121 0x000004B0, //B1200 122 0x00000708, //B1800 123 0x00000960, //B2400 124 0x000012C0, //B4800 125 0x00002580, //B9600 126 0x00004B00, //B19200 127 0x00009600, //B38400 128 0x0000E100, //B57600 129 0x0001C200, //B115200 130 0x00038400, //B230400 131 0x00070800, //460800 132 0x000E1000, //921600 133 }; 134 135 uint32 baudCount = sizeof(baudRates) / sizeof(baudRates[0]); 136 uint32 baudIndex = tios.c_cflag & CBAUD; 137 if (baudIndex > baudCount) 138 baudIndex = baudCount - 1; 139 140 usb_serial_line_coding lineCoding; 141 lineCoding.speed = baudRates[baudIndex]; 142 lineCoding.stopbits = (tios.c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; 143 144 if (tios.c_cflag & PARENB) { 145 lineCoding.parity = LC_PARITY_EVEN; 146 if (tios.c_cflag & PARODD) 147 lineCoding.parity = LC_PARITY_ODD; 148 } else 149 lineCoding.parity = LC_PARITY_NONE; 150 151 lineCoding.databits = (tios.c_cflag & CS8) ? 8 : 7; 152 153 if (lineCoding.speed == 0) { 154 newControl &= 0xfffffffe; 155 lineCoding.speed = fLineCoding.speed; 156 } else 157 newControl = CLS_LINE_DTR; 158 159 if (fControlOut != newControl) { 160 fControlOut = newControl; 161 TRACE("newctrl send to modem: 0x%08x\n", newControl); 162 SetControlLineState(newControl); 163 } 164 165 if (memcmp(&lineCoding, &fLineCoding, sizeof(usb_serial_line_coding)) != 0) { 166 fLineCoding.speed = lineCoding.speed; 167 fLineCoding.stopbits = lineCoding.stopbits; 168 fLineCoding.databits = lineCoding.databits; 169 fLineCoding.parity = lineCoding.parity; 170 TRACE("send to modem: speed %d sb: 0x%08x db: 0x%08x parity: 0x%08x\n", 171 fLineCoding.speed, fLineCoding.stopbits, fLineCoding.databits, 172 fLineCoding.parity); 173 SetLineCoding(&fLineCoding); 174 } 175 } 176 177 178 bool 179 SerialDevice::Service(struct tty *ptty, struct ddrover *ddr, uint flags) 180 { 181 if (&fTTY != ptty) 182 return false; 183 184 if (flags <= TTYGETSIGNALS) { 185 switch (flags) { 186 case TTYENABLE: 187 TRACE("TTYENABLE\n"); 188 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, false); 189 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); 190 fControlOut = CLS_LINE_DTR | CLS_LINE_RTS; 191 SetControlLineState(fControlOut); 192 break; 193 194 case TTYDISABLE: 195 TRACE("TTYDISABLE\n"); 196 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, false); 197 fControlOut = 0x0; 198 SetControlLineState(fControlOut); 199 break; 200 201 case TTYISTOP: 202 TRACE("TTYISTOP\n"); 203 fInputStopped = true; 204 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); 205 break; 206 207 case TTYIRESUME: 208 TRACE("TTYIRESUME\n"); 209 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); 210 fInputStopped = false; 211 break; 212 213 case TTYGETSIGNALS: 214 TRACE("TTYGETSIGNALS\n"); 215 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, true); 216 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); 217 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDSR, false); 218 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWRI, false); 219 break; 220 221 case TTYSETMODES: 222 TRACE("TTYSETMODES\n"); 223 SetModes(); 224 break; 225 226 case TTYOSTART: 227 case TTYOSYNC: 228 case TTYSETBREAK: 229 case TTYCLRBREAK: 230 case TTYSETDTR: 231 case TTYCLRDTR: 232 TRACE("TTY other\n"); 233 break; 234 } 235 236 return true; 237 } 238 239 return false; 240 } 241 242 243 status_t 244 SerialDevice::Open(uint32 flags) 245 { 246 if (fDeviceOpen) 247 return B_BUSY; 248 249 if (fDeviceRemoved) 250 return B_DEV_NOT_READY; 251 252 gTTYModule->ttyinit(&fTTY, true); 253 fTTYFile.tty = &fTTY; 254 fTTYFile.flags = flags; 255 ResetDevice(); 256 257 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 258 if (!ddr) 259 return B_NO_MEMORY; 260 261 gTTYModule->ddacquire(ddr, &gSerialDomain); 262 status_t status = gTTYModule->ttyopen(&fTTYFile, ddr, usb_serial_service); 263 gTTYModule->ddrdone(ddr); 264 265 if (status < B_OK) { 266 TRACE_ALWAYS("open: failed to open tty\n"); 267 return status; 268 } 269 270 fDeviceThread = spawn_kernel_thread(DeviceThread, "usb_serial device thread", 271 B_NORMAL_PRIORITY, this); 272 273 if (fDeviceThread < B_OK) { 274 TRACE_ALWAYS("open: failed to spawn kernel thread\n"); 275 return fDeviceThread; 276 } 277 278 resume_thread(fDeviceThread); 279 280 fControlOut = CLS_LINE_DTR | CLS_LINE_RTS; 281 SetControlLineState(fControlOut); 282 283 status = gUSBModule->queue_interrupt(fControlPipe, fInterruptBuffer, 284 fInterruptBufferSize, InterruptCallbackFunction, this); 285 if (status < B_OK) 286 TRACE_ALWAYS("failed to queue initial interrupt\n"); 287 288 fDeviceOpen = true; 289 return B_OK; 290 } 291 292 293 status_t 294 SerialDevice::Read(char *buffer, size_t *numBytes) 295 { 296 if (fDeviceRemoved) { 297 *numBytes = 0; 298 return B_DEV_NOT_READY; 299 } 300 301 status_t status = mutex_lock(&fReadLock); 302 if (status != B_OK) { 303 TRACE_ALWAYS("read: failed to get read lock\n"); 304 *numBytes = 0; 305 return status; 306 } 307 308 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 309 if (!ddr) { 310 *numBytes = 0; 311 mutex_unlock(&fReadLock); 312 return B_NO_MEMORY; 313 } 314 315 status = gTTYModule->ttyread(&fTTYFile, ddr, buffer, numBytes); 316 gTTYModule->ddrdone(ddr); 317 318 mutex_unlock(&fReadLock); 319 return status; 320 } 321 322 323 status_t 324 SerialDevice::Write(const char *buffer, size_t *numBytes) 325 { 326 size_t bytesLeft = *numBytes; 327 *numBytes = 0; 328 329 status_t status = mutex_lock(&fWriteLock); 330 if (status != B_OK) { 331 TRACE_ALWAYS("write: failed to get write lock\n"); 332 return status; 333 } 334 335 if (fDeviceRemoved) { 336 mutex_unlock(&fWriteLock); 337 return B_DEV_NOT_READY; 338 } 339 340 while (bytesLeft > 0) { 341 size_t length = MIN(bytesLeft, fWriteBufferSize); 342 size_t packetLength = length; 343 OnWrite(buffer, &length, &packetLength); 344 345 status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, 346 packetLength, WriteCallbackFunction, this); 347 if (status < B_OK) { 348 TRACE_ALWAYS("write: queueing failed with status 0x%08x\n", status); 349 break; 350 } 351 352 status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0); 353 if (status < B_OK) { 354 TRACE_ALWAYS("write: failed to get write done sem 0x%08x\n", status); 355 break; 356 } 357 358 if (fStatusWrite != B_OK) { 359 TRACE("write: device status error 0x%08x\n", fStatusWrite); 360 status = gUSBModule->clear_feature(fWritePipe, 361 USB_FEATURE_ENDPOINT_HALT); 362 if (status < B_OK) { 363 TRACE_ALWAYS("write: failed to clear device halt\n"); 364 status = B_ERROR; 365 break; 366 } 367 continue; 368 } 369 370 buffer += length; 371 *numBytes += length; 372 bytesLeft -= length; 373 } 374 375 mutex_unlock(&fWriteLock); 376 return status; 377 } 378 379 380 status_t 381 SerialDevice::Control(uint32 op, void *arg, size_t length) 382 { 383 if (fDeviceRemoved) 384 return B_DEV_NOT_READY; 385 386 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 387 if (!ddr) 388 return B_NO_MEMORY; 389 390 status_t status = gTTYModule->ttycontrol(&fTTYFile, ddr, op, arg, length); 391 gTTYModule->ddrdone(ddr); 392 return status; 393 } 394 395 396 status_t 397 SerialDevice::Select(uint8 event, uint32 ref, selectsync *sync) 398 { 399 if (fDeviceRemoved) 400 return B_DEV_NOT_READY; 401 402 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 403 if (!ddr) 404 return B_NO_MEMORY; 405 406 status_t status = gTTYModule->ttyselect(&fTTYFile, ddr, event, ref, sync); 407 gTTYModule->ddrdone(ddr); 408 return status; 409 } 410 411 412 status_t 413 SerialDevice::DeSelect(uint8 event, selectsync *sync) 414 { 415 if (fDeviceRemoved) 416 return B_DEV_NOT_READY; 417 418 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 419 if (!ddr) 420 return B_NO_MEMORY; 421 422 status_t status = gTTYModule->ttydeselect(&fTTYFile, ddr, event, sync); 423 gTTYModule->ddrdone(ddr); 424 return status; 425 } 426 427 428 status_t 429 SerialDevice::Close() 430 { 431 OnClose(); 432 433 if (!fDeviceRemoved) { 434 gUSBModule->cancel_queued_transfers(fReadPipe); 435 gUSBModule->cancel_queued_transfers(fWritePipe); 436 gUSBModule->cancel_queued_transfers(fControlPipe); 437 } 438 439 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 440 if (!ddr) 441 return B_NO_MEMORY; 442 443 status_t status = gTTYModule->ttyclose(&fTTYFile, ddr); 444 gTTYModule->ddrdone(ddr); 445 446 fDeviceOpen = false; 447 return status; 448 } 449 450 451 status_t 452 SerialDevice::Free() 453 { 454 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 455 if (!ddr) 456 return B_NO_MEMORY; 457 458 status_t status = gTTYModule->ttyfree(&fTTYFile, ddr); 459 gTTYModule->ddrdone(ddr); 460 return status; 461 } 462 463 464 void 465 SerialDevice::Removed() 466 { 467 if (fDeviceRemoved) 468 return; 469 470 // notifies us that the device was removed 471 fDeviceRemoved = true; 472 473 // we need to ensure that we do not use the device anymore 474 fStopDeviceThread = true; 475 fInputStopped = false; 476 gUSBModule->cancel_queued_transfers(fReadPipe); 477 gUSBModule->cancel_queued_transfers(fWritePipe); 478 gUSBModule->cancel_queued_transfers(fControlPipe); 479 480 int32 result = B_OK; 481 wait_for_thread(fDeviceThread, &result); 482 fDeviceThread = -1; 483 484 mutex_lock(&fWriteLock); 485 mutex_unlock(&fWriteLock); 486 } 487 488 489 status_t 490 SerialDevice::AddDevice(const usb_configuration_info *config) 491 { 492 // default implementation - does nothing 493 return B_ERROR; 494 } 495 496 497 status_t 498 SerialDevice::ResetDevice() 499 { 500 // default implementation - does nothing 501 return B_OK; 502 } 503 504 505 status_t 506 SerialDevice::SetLineCoding(usb_serial_line_coding *coding) 507 { 508 // default implementation - does nothing 509 return B_OK; 510 } 511 512 513 status_t 514 SerialDevice::SetControlLineState(uint16 state) 515 { 516 // default implementation - does nothing 517 return B_OK; 518 } 519 520 521 void 522 SerialDevice::OnRead(char **buffer, size_t *numBytes) 523 { 524 // default implementation - does nothing 525 } 526 527 528 void 529 SerialDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) 530 { 531 // default implementation - does nothing 532 } 533 534 535 void 536 SerialDevice::OnClose() 537 { 538 // default implementation - does nothing 539 } 540 541 542 int32 543 SerialDevice::DeviceThread(void *data) 544 { 545 SerialDevice *device = (SerialDevice *)data; 546 547 while (!device->fStopDeviceThread) { 548 status_t status = gUSBModule->queue_bulk(device->fReadPipe, 549 device->fReadBuffer, device->fReadBufferSize, 550 device->ReadCallbackFunction, data); 551 if (status < B_OK) { 552 TRACE_ALWAYS("device thread: queueing failed with error: 0x%08x\n", status); 553 break; 554 } 555 556 status = acquire_sem_etc(device->fDoneRead, 1, B_CAN_INTERRUPT, 0); 557 if (status < B_OK) { 558 TRACE_ALWAYS("device thread: failed to get read done sem 0x%08x\n", status); 559 break; 560 } 561 562 if (device->fStatusRead != B_OK) { 563 TRACE("device thread: device status error 0x%08x\n", 564 device->fStatusRead); 565 if (gUSBModule->clear_feature(device->fReadPipe, 566 USB_FEATURE_ENDPOINT_HALT) != B_OK) { 567 TRACE_ALWAYS("device thread: failed to clear halt feature\n"); 568 break; 569 } 570 } 571 572 char *buffer = device->fReadBuffer; 573 size_t readLength = device->fActualLengthRead; 574 device->OnRead(&buffer, &readLength); 575 if (readLength == 0) 576 continue; 577 578 ddrover *ddr = gTTYModule->ddrstart(NULL); 579 if (!ddr) { 580 TRACE_ALWAYS("device thread: ddrstart problem\n"); 581 return B_NO_MEMORY; 582 } 583 584 while (device->fInputStopped) 585 snooze(100); 586 587 gTTYModule->ttyilock(&device->fTTY, ddr, true); 588 for (size_t i = 0; i < readLength; i++) 589 gTTYModule->ttyin(&device->fTTY, ddr, buffer[i]); 590 591 gTTYModule->ttyilock(&device->fTTY, ddr, false); 592 gTTYModule->ddrdone(ddr); 593 } 594 595 return B_OK; 596 } 597 598 599 void 600 SerialDevice::ReadCallbackFunction(void *cookie, int32 status, void *data, 601 uint32 actualLength) 602 { 603 TRACE_FUNCALLS("read callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 604 cookie, status, data, actualLength); 605 606 SerialDevice *device = (SerialDevice *)cookie; 607 device->fActualLengthRead = actualLength; 608 device->fStatusRead = status; 609 release_sem_etc(device->fDoneRead, 1, B_DO_NOT_RESCHEDULE); 610 } 611 612 613 void 614 SerialDevice::WriteCallbackFunction(void *cookie, int32 status, void *data, 615 uint32 actualLength) 616 { 617 TRACE_FUNCALLS("write callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 618 cookie, status, data, actualLength); 619 620 SerialDevice *device = (SerialDevice *)cookie; 621 device->fActualLengthWrite = actualLength; 622 device->fStatusWrite = status; 623 release_sem_etc(device->fDoneWrite, 1, B_DO_NOT_RESCHEDULE); 624 } 625 626 627 void 628 SerialDevice::InterruptCallbackFunction(void *cookie, int32 status, 629 void *data, uint32 actualLength) 630 { 631 TRACE_FUNCALLS("interrupt callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 632 cookie, status, data, actualLength); 633 634 SerialDevice *device = (SerialDevice *)cookie; 635 device->fActualLengthInterrupt = actualLength; 636 device->fStatusInterrupt = status; 637 638 // ToDo: maybe handle those somehow? 639 640 if (status == B_OK && !device->fDeviceRemoved) { 641 status = gUSBModule->queue_interrupt(device->fControlPipe, 642 device->fInterruptBuffer, device->fInterruptBufferSize, 643 device->InterruptCallbackFunction, device); 644 } 645 } 646 647 648 649 SerialDevice * 650 SerialDevice::MakeDevice(usb_device device, uint16 vendorID, 651 uint16 productID) 652 { 653 const char *description = NULL; 654 655 switch (vendorID) { 656 case VENDOR_IODATA: 657 case VENDOR_ATEN: 658 case VENDOR_TDK: 659 case VENDOR_RATOC: 660 case VENDOR_PROLIFIC: 661 case VENDOR_ELECOM: 662 case VENDOR_SOURCENEXT: 663 case VENDOR_HAL: 664 { 665 switch (productID) { 666 case PRODUCT_PROLIFIC_RSAQ2: description = "PL2303 Serial adapter (IODATA USB-RSAQ2)"; break; 667 case PRODUCT_IODATA_USBRSAQ: description = "I/O Data USB serial adapter USB-RSAQ1"; break; 668 case PRODUCT_ATEN_UC232A: description = "Aten Serial adapter"; break; 669 case PRODUCT_TDK_UHA6400: description = "TDK USB-PHS Adapter UHA6400"; break; 670 case PRODUCT_RATOC_REXUSB60: description = "Ratoc USB serial adapter REX-USB60"; break; 671 case PRODUCT_PROLIFIC_PL2303: description = "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"; break; 672 case PRODUCT_ELECOM_UCSGT: description = "Elecom UC-SGT"; break; 673 case PRODUCT_SOURCENEXT_KEIKAI8: description = "SOURCENEXT KeikaiDenwa 8"; break; 674 case PRODUCT_SOURCENEXT_KEIKAI8_CHG: description = "SOURCENEXT KeikaiDenwa 8 with charger"; break; 675 case PRODUCT_HAL_IMR001: description = "HAL Corporation Crossam2+USB"; break; 676 } 677 678 if (!description) 679 break; 680 681 return new ProlificDevice(device, vendorID, productID, description); 682 } 683 684 case VENDOR_FTDI: 685 { 686 switch (productID) { 687 case PRODUCT_FTDI_8U100AX: description = "FTDI 8U100AX serial converter"; break; 688 case PRODUCT_FTDI_8U232AM: description = "FTDI 8U232AM serial converter"; break; 689 } 690 691 if (!description) 692 break; 693 694 return new FTDIDevice(device, vendorID, productID, description); 695 } 696 697 case VENDOR_PALM: 698 case VENDOR_KLSI: 699 { 700 switch (productID) { 701 case PRODUCT_PALM_CONNECT: description = "PalmConnect RS232"; break; 702 case PRODUCT_KLSI_KL5KUSB105D: description = "KLSI KL5KUSB105D"; break; 703 } 704 705 if (!description) 706 break; 707 708 return new KLSIDevice(device, vendorID, productID, description); 709 } 710 } 711 712 return new ACMDevice(device, vendorID, productID, "CDC ACM compatible device"); 713 } 714