1 /* 2 * Copyright 2009-2010, François Revol, <revol@free.fr>. 3 * Sponsored by TuneTracker Systems. 4 * Based on the Haiku usb_serial driver which is: 5 * 6 * Copyright (c) 2007-2008 by Michael Lotz 7 * Heavily based on the original usb_serial driver which is: 8 * 9 * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li> 10 * Distributed under the terms of the MIT License. 11 */ 12 #include "SerialDevice.h" 13 #include "UART.h" 14 15 SerialDevice::SerialDevice(const struct serial_support_descriptor *device, 16 uint32 ioBase, uint32 irq, const SerialDevice *master) 17 : /*fSupportDescriptor(device->descriptor), 18 fDevice(device), 19 fDescription(device->descriptor->name),*/ 20 fSupportDescriptor(device), 21 fDevice(NULL), 22 fDescription(device->name), 23 // 24 fDeviceOpen(false), 25 fDeviceRemoved(false), 26 fBus(device->bus), 27 fIOBase(ioBase), 28 fIRQ(irq), 29 fMaster(master), 30 fBufferArea(-1), 31 fReadBuffer(NULL), 32 fReadBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), 33 fWriteBuffer(NULL), 34 fWriteBufferSize(ROUNDUP(DEF_BUFFER_SIZE, 16)), 35 fInterruptBuffer(NULL), 36 fInterruptBufferSize(16), 37 fDoneRead(-1), 38 fDoneWrite(-1), 39 fControlOut(0), 40 fInputStopped(false), 41 fDeviceThread(-1), 42 fStopDeviceThread(false) 43 { 44 memset(&fTTYFile, 0, sizeof(ttyfile)); 45 memset(&fTTY, 0, sizeof(tty)); 46 memset(&fRover, 0, sizeof(ddrover)); 47 } 48 49 50 SerialDevice::~SerialDevice() 51 { 52 Removed(); 53 54 if (fDoneRead >= B_OK) 55 delete_sem(fDoneRead); 56 if (fDoneWrite >= B_OK) 57 delete_sem(fDoneWrite); 58 59 if (fBufferArea >= B_OK) 60 delete_area(fBufferArea); 61 62 mutex_destroy(&fReadLock); 63 mutex_destroy(&fWriteLock); 64 } 65 66 67 status_t 68 SerialDevice::Init() 69 { 70 fDoneRead = create_sem(0, "usb_serial:done_read"); 71 fDoneWrite = create_sem(0, "usb_serial:done_write"); 72 mutex_init(&fReadLock, "usb_serial:read_lock"); 73 mutex_init(&fWriteLock, "usb_serial:write_lock"); 74 75 size_t totalBuffers = fReadBufferSize + fWriteBufferSize + fInterruptBufferSize; 76 fBufferArea = create_area("usb_serial:buffers_area", (void **)&fReadBuffer, 77 B_ANY_KERNEL_ADDRESS, ROUNDUP(totalBuffers, B_PAGE_SIZE), B_CONTIGUOUS, 78 B_READ_AREA | B_WRITE_AREA); 79 80 fWriteBuffer = fReadBuffer + fReadBufferSize; 81 fInterruptBuffer = fWriteBuffer + fWriteBufferSize; 82 83 // disable DLAB 84 WriteReg8(LCR, 0); 85 86 return B_OK; 87 } 88 89 90 void 91 SerialDevice::SetModes() 92 { 93 struct termios tios; 94 memcpy(&tios, &fTTY.t, sizeof(struct termios)); 95 //TRACE_FUNCRES(trace_termios, &tios); 96 spin(10000); 97 uint32 baudIndex = tios.c_cflag & CBAUD; 98 if (baudIndex > BLAST) 99 baudIndex = BLAST; 100 101 uint8 lcr = 0; 102 uint16 divisor = SupportDescriptor()->bauds[baudIndex]; 103 104 switch (tios.c_cflag & CSIZE) { 105 #if CS5 != CS7 106 // in case someday... 107 case CS5: 108 lcr |= LCR_5BIT; 109 break; 110 case CS6: 111 lcr |= LCR_6BIT; 112 break; 113 #endif 114 case CS7: 115 lcr |= LCR_7BIT; 116 break; 117 case CS8: 118 default: 119 lcr |= LCR_8BIT; 120 break; 121 } 122 123 if (tios.c_cflag & CSTOPB) 124 lcr |= LCR_2STOP; 125 if (tios.c_cflag & PARENB) 126 lcr |= LCR_P_EN; 127 if (tios.c_cflag & PARODD == 0) 128 lcr |= LCR_P_EVEN; 129 130 if (baudIndex == B0) { 131 // disable 132 MaskReg8(MCR, MCR_DTR); 133 } else { 134 // set FCR now, 135 // 16650 and later chips have another reg at 2 when DLAB=1 136 uint8 fcr = FCR_ENABLE | FCR_RX_RST | FCR_TX_RST | FCR_F_8; 137 // enable fifo 138 //fcr = 0; 139 WriteReg8(FCR, fcr); 140 141 // unmask the divisor latch regs 142 WriteReg8(LCR, LCR_DLAB); 143 // set divisor 144 WriteReg8(DLLB, divisor & 0x00ff); 145 WriteReg8(DLHB, divisor >> 8); 146 //WriteReg8(2,0); 147 148 } 149 // set control lines, and disable divisor latch reg 150 WriteReg8(LCR, lcr); 151 152 153 #if 0 154 uint16 newControl = fControlOut; 155 156 static uint32 baudRates[] = { 157 0x00000000, //B0 158 0x00000032, //B50 159 0x0000004B, //B75 160 0x0000006E, //B110 161 0x00000086, //B134 162 0x00000096, //B150 163 0x000000C8, //B200 164 0x0000012C, //B300 165 0x00000258, //B600 166 0x000004B0, //B1200 167 0x00000708, //B1800 168 0x00000960, //B2400 169 0x000012C0, //B4800 170 0x00002580, //B9600 171 0x00004B00, //B19200 172 0x00009600, //B38400 173 0x0000E100, //B57600 174 0x0001C200, //B115200 175 0x00038400, //B230400 176 0x00070800, //460800 177 0x000E1000, //921600 178 }; 179 180 usb_serial_line_coding lineCoding; 181 lineCoding.speed = baudRates[baudIndex]; 182 lineCoding.stopbits = (tios.c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; 183 184 if (tios.c_cflag & PARENB) { 185 lineCoding.parity = LC_PARITY_EVEN; 186 if (tios.c_cflag & PARODD) 187 lineCoding.parity = LC_PARITY_ODD; 188 } else 189 lineCoding.parity = LC_PARITY_NONE; 190 191 lineCoding.databits = (tios.c_cflag & CS8) ? 8 : 7; 192 193 if (lineCoding.speed == 0) { 194 newControl &= 0xfffffffe; 195 lineCoding.speed = fLineCoding.speed; 196 } else 197 newControl = CLS_LINE_DTR; 198 199 if (fControlOut != newControl) { 200 fControlOut = newControl; 201 TRACE("newctrl send to modem: 0x%08x\n", newControl); 202 SetControlLineState(newControl); 203 } 204 205 if (memcmp(&lineCoding, &fLineCoding, sizeof(usb_serial_line_coding)) != 0) { 206 fLineCoding.speed = lineCoding.speed; 207 fLineCoding.stopbits = lineCoding.stopbits; 208 fLineCoding.databits = lineCoding.databits; 209 fLineCoding.parity = lineCoding.parity; 210 TRACE("send to modem: speed %d sb: 0x%08x db: 0x%08x parity: 0x%08x\n", 211 fLineCoding.speed, fLineCoding.stopbits, fLineCoding.databits, 212 fLineCoding.parity); 213 SetLineCoding(&fLineCoding); 214 } 215 #endif 216 } 217 218 219 bool 220 SerialDevice::Service(struct tty *ptty, struct ddrover *ddr, uint flags) 221 { 222 uint8 msr; 223 status_t err; 224 225 if (&fTTY != ptty) 226 return false; 227 228 TRACE("%s(,,0x%08lx)\n", __FUNCTION__, flags); 229 230 if (flags <= TTYGETSIGNALS) { 231 switch (flags) { 232 case TTYENABLE: 233 TRACE("TTYENABLE\n"); 234 235 SetModes(); 236 err = install_io_interrupt_handler(IRQ(), pc_serial_interrupt, this, 0); 237 TRACE("installing irq handler for %d: %s\n", IRQ(), strerror(err)); 238 msr = ReadReg8(MSR); 239 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); 240 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); 241 // 242 WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN /*| MCR_LOOP*//*XXXXXXX*/); 243 // enable irqs 244 WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); 245 //WriteReg8(IER, IER_RDA); 246 break; 247 248 case TTYDISABLE: 249 TRACE("TTYDISABLE\n"); 250 // remove the handler 251 remove_io_interrupt_handler(IRQ(), pc_serial_interrupt, this); 252 // disable IRQ 253 WriteReg8(IER, 0); 254 WriteReg8(MCR, 0); 255 msr = ReadReg8(MSR); 256 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); 257 break; 258 259 case TTYISTOP: 260 TRACE("TTYISTOP\n"); 261 MaskReg8(MCR, MCR_RTS); 262 //fInputStopped = true; 263 //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); 264 break; 265 266 case TTYIRESUME: 267 TRACE("TTYIRESUME\n"); 268 OrReg8(MCR, MCR_RTS); 269 //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); 270 //fInputStopped = false; 271 break; 272 273 case TTYGETSIGNALS: 274 TRACE("TTYGETSIGNALS\n"); 275 msr = ReadReg8(MSR); 276 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); 277 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); 278 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDSR, msr & MSR_DSR); 279 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWRI, msr & MSR_RI); 280 break; 281 282 case TTYSETMODES: 283 TRACE("TTYSETMODES\n"); 284 SetModes(); 285 //WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); 286 break; 287 288 case TTYOSTART: 289 TRACE("TTYOSTART\n"); 290 // enable irqs 291 WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE); 292 break; 293 case TTYOSYNC: 294 TRACE("TTYOSYNC\n"); 295 return (ReadReg8(LSR) & (LSR_THRE | LSR_TSRE)) == (LSR_THRE | LSR_TSRE); 296 break; 297 case TTYSETBREAK: 298 TRACE("TTYSETBREAK\n"); 299 OrReg8(LCR, LCR_BREAK); 300 break; 301 case TTYCLRBREAK: 302 TRACE("TTYCLRBREAK\n"); 303 MaskReg8(LCR, LCR_BREAK); 304 break; 305 case TTYSETDTR: 306 TRACE("TTYSETDTR\n"); 307 OrReg8(MCR, MCR_DTR); 308 break; 309 case TTYCLRDTR: 310 TRACE("TTYCLRDTR\n"); 311 MaskReg8(MCR, MCR_DTR); 312 break; 313 } 314 315 return true; 316 } 317 318 return false; 319 } 320 321 322 int32 323 SerialDevice::InterruptHandler() 324 { 325 int32 ret = B_UNHANDLED_INTERRUPT; 326 gTTYModule->ddrstart(&fRover); 327 gTTYModule->ttyilock(&fTTY, &fRover, true); 328 329 uint8 iir, lsr, msr; 330 int count; 331 332 while (((iir = ReadReg8(IIR)) & IIR_PENDING) == 0) { // 0 means yes 333 int fifoavail = 1; 334 335 //DEBUG 336 // for (count = 0; ReadReg8(LSR) & LSR_DR; count++) 337 // gTTYModule->ttyin(&fTTY, &fRover, ReadReg8(RBR)); 338 339 switch (iir & (IIR_IMASK | IIR_TO)) { 340 case IIR_THRE: 341 TRACE(("IIR_THRE\n")); 342 // check how much fifo we can use 343 //XXX: move to Init() ? 344 if (iir & IIR_FMASK == IIR_FMASK) 345 fifoavail = 16; 346 if (iir & IIR_F64EN) 347 fifoavail = 64; 348 for (int i = 0; i < fifoavail; i++) { 349 int chr = gTTYModule->ttyout(&fTTY, &fRover); 350 if (chr < 0) { 351 //WriteReg8(THB, (uint8)chr); 352 break; 353 } 354 WriteReg8(THB, (uint8)chr); 355 } 356 break; 357 case IIR_TO: 358 case IIR_TO | IIR_RDA: 359 // timeout: FALLTHROUGH 360 case IIR_RDA: 361 TRACE(("IIR_TO/RDA\n")); 362 // while data is ready... get it 363 while (ReadReg8(LSR) & LSR_DR) 364 gTTYModule->ttyin(&fTTY, &fRover, ReadReg8(RBR)); 365 break; 366 case IIR_RLS: 367 TRACE(("IIR_RLS\n")); 368 // ack 369 lsr = ReadReg8(LSR); 370 //XXX: handle this somehow 371 break; 372 case IIR_MS: 373 TRACE(("IIR_MS\n")); 374 // modem signals changed 375 msr = ReadReg8(MSR); 376 if (msr & MSR_DDCD) 377 gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWDCD, msr & MSR_DCD); 378 if (msr & MSR_DCTS) 379 gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWCTS, msr & MSR_CTS); 380 if (msr & MSR_DDSR) 381 gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWDSR, msr & MSR_DSR); 382 if (msr & MSR_TERI) 383 gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWRI, msr & MSR_RI); 384 break; 385 default: 386 TRACE(("IIR_?\n")); 387 // something happened 388 break; 389 } 390 ret = B_HANDLED_INTERRUPT; 391 TRACE(("IRQ:h\n")); 392 } 393 394 395 gTTYModule->ttyilock(&fTTY, &fRover, false); 396 gTTYModule->ddrdone(&fRover); 397 TRACE_FUNCRET("< IRQ:%d\n", ret); 398 return ret; 399 } 400 401 402 status_t 403 SerialDevice::Open(uint32 flags) 404 { 405 if (fDeviceOpen) 406 return B_BUSY; 407 408 if (fDeviceRemoved) 409 return B_DEV_NOT_READY; 410 411 gTTYModule->ttyinit(&fTTY, false); 412 fTTYFile.tty = &fTTY; 413 fTTYFile.flags = flags; 414 ResetDevice(); 415 416 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 417 if (!ddr) 418 return B_NO_MEMORY; 419 420 gTTYModule->ddacquire(ddr, &gSerialDomain); 421 status_t status = gTTYModule->ttyopen(&fTTYFile, ddr, pc_serial_service); 422 gTTYModule->ddrdone(ddr); 423 424 if (status < B_OK) { 425 TRACE_ALWAYS("open: failed to open tty\n"); 426 return status; 427 } 428 429 #if 0 430 fDeviceThread = spawn_kernel_thread(DeviceThread, "usb_serial device thread", 431 B_NORMAL_PRIORITY, this); 432 433 if (fDeviceThread < B_OK) { 434 TRACE_ALWAYS("open: failed to spawn kernel thread\n"); 435 return fDeviceThread; 436 } 437 438 resume_thread(fDeviceThread); 439 440 fControlOut = CLS_LINE_DTR | CLS_LINE_RTS; 441 SetControlLineState(fControlOut); 442 443 status = gUSBModule->queue_interrupt(fControlPipe, fInterruptBuffer, 444 fInterruptBufferSize, InterruptCallbackFunction, this); 445 if (status < B_OK) 446 TRACE_ALWAYS("failed to queue initial interrupt\n"); 447 448 #endif 449 fDeviceOpen = true; 450 return B_OK; 451 } 452 453 454 status_t 455 SerialDevice::Read(char *buffer, size_t *numBytes) 456 { 457 if (fDeviceRemoved) { 458 *numBytes = 0; 459 return B_DEV_NOT_READY; 460 } 461 462 status_t status; 463 #if 0 464 status_t status = mutex_lock(&fReadLock); 465 if (status != B_OK) { 466 TRACE_ALWAYS("read: failed to get read lock\n"); 467 *numBytes = 0; 468 return status; 469 } 470 #endif 471 472 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 473 if (!ddr) { 474 *numBytes = 0; 475 #if 0 476 mutex_unlock(&fReadLock); 477 #endif 478 return B_NO_MEMORY; 479 } 480 481 status = gTTYModule->ttyread(&fTTYFile, ddr, buffer, numBytes); 482 gTTYModule->ddrdone(ddr); 483 484 #if 0 485 mutex_unlock(&fReadLock); 486 #endif 487 return status; 488 } 489 490 491 status_t 492 SerialDevice::Write(const char *buffer, size_t *numBytes) 493 { 494 size_t bytesLeft = *numBytes; 495 //*numBytes = 0; 496 497 status_t status = EINVAL; 498 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 499 if (!ddr) { 500 *numBytes = 0; 501 return B_ERROR; 502 } 503 504 status = gTTYModule->ttywrite(&fTTYFile, ddr, buffer, numBytes); 505 gTTYModule->ddrdone(ddr); 506 507 #if 0 508 status_t status = mutex_lock(&fWriteLock); 509 if (status != B_OK) { 510 TRACE_ALWAYS("write: failed to get write lock\n"); 511 return status; 512 } 513 514 if (fDeviceRemoved) { 515 mutex_unlock(&fWriteLock); 516 return B_DEV_NOT_READY; 517 } 518 519 while (bytesLeft > 0) { 520 size_t length = MIN(bytesLeft, fWriteBufferSize); 521 size_t packetLength = length; 522 OnWrite(buffer, &length, &packetLength); 523 524 status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, 525 packetLength, WriteCallbackFunction, this); 526 if (status < B_OK) { 527 TRACE_ALWAYS("write: queueing failed with status 0x%08x\n", status); 528 break; 529 } 530 531 status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0); 532 if (status < B_OK) { 533 TRACE_ALWAYS("write: failed to get write done sem 0x%08x\n", status); 534 break; 535 } 536 537 if (fStatusWrite != B_OK) { 538 TRACE("write: device status error 0x%08x\n", fStatusWrite); 539 status = gUSBModule->clear_feature(fWritePipe, 540 USB_FEATURE_ENDPOINT_HALT); 541 if (status < B_OK) { 542 TRACE_ALWAYS("write: failed to clear device halt\n"); 543 status = B_ERROR; 544 break; 545 } 546 continue; 547 } 548 549 buffer += length; 550 *numBytes += length; 551 bytesLeft -= length; 552 } 553 554 mutex_unlock(&fWriteLock); 555 #endif 556 return status; 557 } 558 559 560 status_t 561 SerialDevice::Control(uint32 op, void *arg, size_t length) 562 { 563 if (fDeviceRemoved) 564 return B_DEV_NOT_READY; 565 566 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 567 if (!ddr) 568 return B_NO_MEMORY; 569 570 status_t status = gTTYModule->ttycontrol(&fTTYFile, ddr, op, arg, length); 571 gTTYModule->ddrdone(ddr); 572 return status; 573 } 574 575 576 status_t 577 SerialDevice::Select(uint8 event, uint32 ref, selectsync *sync) 578 { 579 if (fDeviceRemoved) 580 return B_DEV_NOT_READY; 581 582 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 583 if (!ddr) 584 return B_NO_MEMORY; 585 586 status_t status = gTTYModule->ttyselect(&fTTYFile, ddr, event, ref, sync); 587 gTTYModule->ddrdone(ddr); 588 return status; 589 } 590 591 592 status_t 593 SerialDevice::DeSelect(uint8 event, selectsync *sync) 594 { 595 if (fDeviceRemoved) 596 return B_DEV_NOT_READY; 597 598 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 599 if (!ddr) 600 return B_NO_MEMORY; 601 602 status_t status = gTTYModule->ttydeselect(&fTTYFile, ddr, event, sync); 603 gTTYModule->ddrdone(ddr); 604 return status; 605 } 606 607 608 status_t 609 SerialDevice::Close() 610 { 611 OnClose(); 612 613 if (!fDeviceRemoved) { 614 #if 0 615 gUSBModule->cancel_queued_transfers(fReadPipe); 616 gUSBModule->cancel_queued_transfers(fWritePipe); 617 gUSBModule->cancel_queued_transfers(fControlPipe); 618 #endif 619 } 620 621 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 622 if (!ddr) 623 return B_NO_MEMORY; 624 625 status_t status = gTTYModule->ttyclose(&fTTYFile, ddr); 626 gTTYModule->ddrdone(ddr); 627 628 fDeviceOpen = false; 629 return status; 630 } 631 632 633 status_t 634 SerialDevice::Free() 635 { 636 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 637 if (!ddr) 638 return B_NO_MEMORY; 639 640 status_t status = gTTYModule->ttyfree(&fTTYFile, ddr); 641 gTTYModule->ddrdone(ddr); 642 return status; 643 } 644 645 646 void 647 SerialDevice::Removed() 648 { 649 if (fDeviceRemoved) 650 return; 651 652 // notifies us that the device was removed 653 fDeviceRemoved = true; 654 655 // we need to ensure that we do not use the device anymore 656 fStopDeviceThread = true; 657 fInputStopped = false; 658 #if 0 659 gUSBModule->cancel_queued_transfers(fReadPipe); 660 gUSBModule->cancel_queued_transfers(fWritePipe); 661 gUSBModule->cancel_queued_transfers(fControlPipe); 662 #endif 663 664 int32 result = B_OK; 665 //wait_for_thread(fDeviceThread, &result); 666 fDeviceThread = -1; 667 668 mutex_lock(&fWriteLock); 669 mutex_unlock(&fWriteLock); 670 } 671 672 673 status_t 674 SerialDevice::AddDevice(const serial_config_descriptor *config) 675 { 676 // default implementation - does nothing 677 return B_ERROR; 678 } 679 680 681 status_t 682 SerialDevice::ResetDevice() 683 { 684 // default implementation - does nothing 685 return B_OK; 686 } 687 688 689 #if 0 690 status_t 691 SerialDevice::SetLineCoding(usb_serial_line_coding *coding) 692 { 693 // default implementation - does nothing 694 return B_OK; 695 } 696 #endif 697 698 status_t 699 SerialDevice::SetControlLineState(uint16 state) 700 { 701 // default implementation - does nothing 702 return B_OK; 703 } 704 705 706 void 707 SerialDevice::OnRead(char **buffer, size_t *numBytes) 708 { 709 // default implementation - does nothing 710 } 711 712 713 void 714 SerialDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) 715 { 716 // default implementation - does nothing 717 } 718 719 720 void 721 SerialDevice::OnClose() 722 { 723 // default implementation - does nothing 724 } 725 726 727 int32 728 SerialDevice::DeviceThread(void *data) 729 { 730 SerialDevice *device = (SerialDevice *)data; 731 #if 0 732 733 while (!device->fStopDeviceThread) { 734 status_t status = gUSBModule->queue_bulk(device->fReadPipe, 735 device->fReadBuffer, device->fReadBufferSize, 736 device->ReadCallbackFunction, data); 737 if (status < B_OK) { 738 TRACE_ALWAYS("device thread: queueing failed with error: 0x%08x\n", status); 739 break; 740 } 741 742 status = acquire_sem_etc(device->fDoneRead, 1, B_CAN_INTERRUPT, 0); 743 if (status < B_OK) { 744 TRACE_ALWAYS("device thread: failed to get read done sem 0x%08x\n", status); 745 break; 746 } 747 748 if (device->fStatusRead != B_OK) { 749 TRACE("device thread: device status error 0x%08x\n", 750 device->fStatusRead); 751 if (gUSBModule->clear_feature(device->fReadPipe, 752 USB_FEATURE_ENDPOINT_HALT) != B_OK) { 753 TRACE_ALWAYS("device thread: failed to clear halt feature\n"); 754 break; 755 } 756 } 757 758 char *buffer = device->fReadBuffer; 759 size_t readLength = device->fActualLengthRead; 760 device->OnRead(&buffer, &readLength); 761 if (readLength == 0) 762 continue; 763 764 ddrover *ddr = gTTYModule->ddrstart(NULL); 765 if (!ddr) { 766 TRACE_ALWAYS("device thread: ddrstart problem\n"); 767 return B_NO_MEMORY; 768 } 769 770 while (device->fInputStopped) 771 snooze(100); 772 773 gTTYModule->ttyilock(&device->fTTY, ddr, true); 774 for (size_t i = 0; i < readLength; i++) 775 gTTYModule->ttyin(&device->fTTY, ddr, buffer[i]); 776 777 gTTYModule->ttyilock(&device->fTTY, ddr, false); 778 gTTYModule->ddrdone(ddr); 779 } 780 781 #endif 782 return B_OK; 783 } 784 785 786 void 787 SerialDevice::ReadCallbackFunction(void *cookie, int32 status, void *data, 788 uint32 actualLength) 789 { 790 TRACE_FUNCALLS("read callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 791 cookie, status, data, actualLength); 792 793 SerialDevice *device = (SerialDevice *)cookie; 794 device->fActualLengthRead = actualLength; 795 device->fStatusRead = status; 796 release_sem_etc(device->fDoneRead, 1, B_DO_NOT_RESCHEDULE); 797 } 798 799 800 void 801 SerialDevice::WriteCallbackFunction(void *cookie, int32 status, void *data, 802 uint32 actualLength) 803 { 804 TRACE_FUNCALLS("write callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 805 cookie, status, data, actualLength); 806 807 SerialDevice *device = (SerialDevice *)cookie; 808 device->fActualLengthWrite = actualLength; 809 device->fStatusWrite = status; 810 release_sem_etc(device->fDoneWrite, 1, B_DO_NOT_RESCHEDULE); 811 } 812 813 814 void 815 SerialDevice::InterruptCallbackFunction(void *cookie, int32 status, 816 void *data, uint32 actualLength) 817 { 818 TRACE_FUNCALLS("interrupt callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 819 cookie, status, data, actualLength); 820 821 SerialDevice *device = (SerialDevice *)cookie; 822 device->fActualLengthInterrupt = actualLength; 823 device->fStatusInterrupt = status; 824 825 // ToDo: maybe handle those somehow? 826 827 if (status == B_OK && !device->fDeviceRemoved) { 828 #if 0 829 status = gUSBModule->queue_interrupt(device->fControlPipe, 830 device->fInterruptBuffer, device->fInterruptBufferSize, 831 device->InterruptCallbackFunction, device); 832 #endif 833 } 834 } 835 836 837 838 #if 0 839 SerialDevice * 840 SerialDevice::MakeDevice(usb_device device, uint16 vendorID, 841 uint16 productID) 842 { 843 const char *description = NULL; 844 845 switch (vendorID) { 846 case VENDOR_IODATA: 847 case VENDOR_ATEN: 848 case VENDOR_TDK: 849 case VENDOR_RATOC: 850 case VENDOR_PROLIFIC: 851 case VENDOR_ELECOM: 852 case VENDOR_SOURCENEXT: 853 case VENDOR_HAL: 854 { 855 switch (productID) { 856 case PRODUCT_PROLIFIC_RSAQ2: description = "PL2303 Serial adapter (IODATA USB-RSAQ2)"; break; 857 case PRODUCT_IODATA_USBRSAQ: description = "I/O Data USB serial adapter USB-RSAQ1"; break; 858 case PRODUCT_ATEN_UC232A: description = "Aten Serial adapter"; break; 859 case PRODUCT_TDK_UHA6400: description = "TDK USB-PHS Adapter UHA6400"; break; 860 case PRODUCT_RATOC_REXUSB60: description = "Ratoc USB serial adapter REX-USB60"; break; 861 case PRODUCT_PROLIFIC_PL2303: description = "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"; break; 862 case PRODUCT_ELECOM_UCSGT: description = "Elecom UC-SGT"; break; 863 case PRODUCT_SOURCENEXT_KEIKAI8: description = "SOURCENEXT KeikaiDenwa 8"; break; 864 case PRODUCT_SOURCENEXT_KEIKAI8_CHG: description = "SOURCENEXT KeikaiDenwa 8 with charger"; break; 865 case PRODUCT_HAL_IMR001: description = "HAL Corporation Crossam2+USB"; break; 866 } 867 868 if (!description) 869 break; 870 871 return new ProlificDevice(device, vendorID, productID, description); 872 } 873 874 case VENDOR_FTDI: 875 { 876 switch (productID) { 877 case PRODUCT_FTDI_8U100AX: description = "FTDI 8U100AX serial converter"; break; 878 case PRODUCT_FTDI_8U232AM: description = "FTDI 8U232AM serial converter"; break; 879 } 880 881 if (!description) 882 break; 883 884 return new FTDIDevice(device, vendorID, productID, description); 885 } 886 887 case VENDOR_PALM: 888 case VENDOR_KLSI: 889 { 890 switch (productID) { 891 case PRODUCT_PALM_CONNECT: description = "PalmConnect RS232"; break; 892 case PRODUCT_KLSI_KL5KUSB105D: description = "KLSI KL5KUSB105D"; break; 893 } 894 895 if (!description) 896 break; 897 898 return new KLSIDevice(device, vendorID, productID, description); 899 } 900 } 901 902 return new ACMDevice(device, vendorID, productID, "CDC ACM compatible device"); 903 } 904 #endif 905 906 907 uint8 908 SerialDevice::ReadReg8(int reg) 909 { 910 uint8 ret; 911 switch (fBus) { 912 case B_ISA_BUS: 913 ret = gISAModule->read_io_8(IOBase() + reg); 914 break; 915 case B_PCI_BUS: 916 ret = gPCIModule->read_io_8(IOBase() + reg); 917 break; 918 default: 919 TRACE_ALWAYS("%s: unknown bus!\n", __FUNCTION__); 920 ret = 0; 921 //XXX:pcmcia ? 922 } 923 TRACE/*_ALWAYS*/("RR8(%d) = %d [%02x]\n", reg, ret, ret); 924 //spin(1000); 925 return ret; 926 } 927 928 void 929 SerialDevice::WriteReg8(int reg, uint8 value) 930 { 931 // TRACE_ALWAYS("WR8(0x%04x+%d, %d [0x%x])\n", IOBase(), reg, value, value); 932 TRACE/*_ALWAYS*/("WR8(%d, %d [0x%x])\n", reg, value, value); 933 switch (fBus) { 934 case B_ISA_BUS: 935 gISAModule->write_io_8(IOBase() + reg, value); 936 break; 937 case B_PCI_BUS: 938 gPCIModule->write_io_8(IOBase() + reg, value); 939 break; 940 default: 941 TRACE_ALWAYS("%s: unknown bus!\n", __FUNCTION__); 942 //XXX:pcmcia ? 943 } 944 //spin(10000); 945 } 946 947 948 void 949 SerialDevice::OrReg8(int reg, uint8 value) 950 { 951 WriteReg8(reg, ReadReg8(reg) | value); 952 } 953 954 955 void 956 SerialDevice::AndReg8(int reg, uint8 value) 957 { 958 WriteReg8(reg, ReadReg8(reg) & value); 959 } 960 961 962 void 963 SerialDevice::MaskReg8(int reg, uint8 value) 964 { 965 WriteReg8(reg, ReadReg8(reg) & ~value); 966 } 967