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