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