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 #ifdef __HAIKU__ 42 fMasterTTY(NULL), 43 fSlaveTTY(NULL), 44 fTTYCookie(NULL), 45 #endif /* __HAIKU__ */ 46 fDeviceThread(-1), 47 fStopDeviceThread(false) 48 { 49 #ifdef __BEOS__ 50 memset(&fTTYFile, 0, sizeof(ttyfile)); 51 memset(&fTTY, 0, sizeof(tty)); 52 memset(&fRover, 0, sizeof(ddrover)); 53 #endif /* __BEOS__ */ 54 } 55 56 57 SerialDevice::~SerialDevice() 58 { 59 Removed(); 60 61 if (fDoneRead >= B_OK) 62 delete_sem(fDoneRead); 63 if (fDoneWrite >= B_OK) 64 delete_sem(fDoneWrite); 65 66 if (fBufferArea >= B_OK) 67 delete_area(fBufferArea); 68 69 mutex_destroy(&fReadLock); 70 mutex_destroy(&fWriteLock); 71 } 72 73 74 status_t 75 SerialDevice::Init() 76 { 77 fDoneRead = create_sem(0, "usb_serial:done_read"); 78 fDoneWrite = create_sem(0, "usb_serial:done_write"); 79 mutex_init(&fReadLock, "usb_serial:read_lock"); 80 mutex_init(&fWriteLock, "usb_serial:write_lock"); 81 82 size_t totalBuffers = fReadBufferSize + fWriteBufferSize + fInterruptBufferSize; 83 fBufferArea = create_area("usb_serial:buffers_area", (void **)&fReadBuffer, 84 B_ANY_KERNEL_ADDRESS, ROUNDUP(totalBuffers, B_PAGE_SIZE), B_CONTIGUOUS, 85 B_READ_AREA | B_WRITE_AREA); 86 87 fWriteBuffer = fReadBuffer + fReadBufferSize; 88 fInterruptBuffer = fWriteBuffer + fWriteBufferSize; 89 90 // disable DLAB 91 WriteReg8(LCR, 0); 92 93 return B_OK; 94 } 95 96 97 #ifdef __BEOS__ 98 void 99 SerialDevice::SetModes() 100 { 101 struct termios tios; 102 memcpy(&tios, &fTTY.t, sizeof(struct termios)); 103 SetModes(&tios); 104 } 105 #endif /* __BEOS__ */ 106 107 108 void 109 SerialDevice::SetModes(struct termios *tios) 110 { 111 //TRACE_FUNCRES(trace_termios, tios); 112 spin(10000); 113 uint32 baudIndex = tios->c_cflag & CBAUD; 114 if (baudIndex > BLAST) 115 baudIndex = BLAST; 116 117 uint8 lcr = 0; 118 uint16 divisor = SupportDescriptor()->bauds[baudIndex]; 119 120 switch (tios->c_cflag & CSIZE) { 121 #if CS5 != CS7 122 // in case someday... 123 case CS5: 124 lcr |= LCR_5BIT; 125 break; 126 case CS6: 127 lcr |= LCR_6BIT; 128 break; 129 #endif 130 case CS7: 131 lcr |= LCR_7BIT; 132 break; 133 case CS8: 134 default: 135 lcr |= LCR_8BIT; 136 break; 137 } 138 139 if (tios->c_cflag & CSTOPB) 140 lcr |= LCR_2STOP; 141 if (tios->c_cflag & PARENB) 142 lcr |= LCR_P_EN; 143 if ((tios->c_cflag & PARODD) == 0) 144 lcr |= LCR_P_EVEN; 145 146 if (baudIndex == B0) { 147 // disable 148 MaskReg8(MCR, MCR_DTR); 149 } else { 150 // set FCR now, 151 // 16650 and later chips have another reg at 2 when DLAB=1 152 uint8 fcr = FCR_ENABLE | FCR_RX_RST | FCR_TX_RST | FCR_F_8; 153 // enable fifo 154 //fcr = 0; 155 WriteReg8(FCR, fcr); 156 157 // unmask the divisor latch regs 158 WriteReg8(LCR, LCR_DLAB); 159 // set divisor 160 WriteReg8(DLLB, divisor & 0x00ff); 161 WriteReg8(DLHB, divisor >> 8); 162 //WriteReg8(2,0); 163 164 } 165 // set control lines, and disable divisor latch reg 166 WriteReg8(LCR, lcr); 167 168 169 #if 0 170 uint16 newControl = fControlOut; 171 172 static uint32 baudRates[] = { 173 0x00000000, //B0 174 0x00000032, //B50 175 0x0000004B, //B75 176 0x0000006E, //B110 177 0x00000086, //B134 178 0x00000096, //B150 179 0x000000C8, //B200 180 0x0000012C, //B300 181 0x00000258, //B600 182 0x000004B0, //B1200 183 0x00000708, //B1800 184 0x00000960, //B2400 185 0x000012C0, //B4800 186 0x00002580, //B9600 187 0x00004B00, //B19200 188 0x00009600, //B38400 189 0x0000E100, //B57600 190 0x0001C200, //B115200 191 0x00038400, //B230400 192 0x00070800, //460800 193 0x000E1000, //921600 194 }; 195 196 usb_serial_line_coding lineCoding; 197 lineCoding.speed = baudRates[baudIndex]; 198 lineCoding.stopbits = (tios->c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; 199 200 if (tios->c_cflag & PARENB) { 201 lineCoding.parity = LC_PARITY_EVEN; 202 if (tios->c_cflag & PARODD) 203 lineCoding.parity = LC_PARITY_ODD; 204 } else 205 lineCoding.parity = LC_PARITY_NONE; 206 207 lineCoding.databits = (tios->c_cflag & CS8) ? 8 : 7; 208 209 if (lineCoding.speed == 0) { 210 newControl &= 0xfffffffe; 211 lineCoding.speed = fLineCoding.speed; 212 } else 213 newControl = CLS_LINE_DTR; 214 215 if (fControlOut != newControl) { 216 fControlOut = newControl; 217 TRACE("newctrl send to modem: 0x%08x\n", newControl); 218 SetControlLineState(newControl); 219 } 220 221 if (memcmp(&lineCoding, &fLineCoding, sizeof(usb_serial_line_coding)) != 0) { 222 fLineCoding.speed = lineCoding.speed; 223 fLineCoding.stopbits = lineCoding.stopbits; 224 fLineCoding.databits = lineCoding.databits; 225 fLineCoding.parity = lineCoding.parity; 226 TRACE("send to modem: speed %d sb: 0x%08x db: 0x%08x parity: 0x%08x\n", 227 fLineCoding.speed, fLineCoding.stopbits, fLineCoding.databits, 228 fLineCoding.parity); 229 SetLineCoding(&fLineCoding); 230 } 231 #endif 232 } 233 234 235 #ifdef __HAIKU__ 236 237 238 bool 239 SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length) 240 { 241 uint8 msr; 242 status_t err; 243 244 if (tty != fMasterTTY) 245 return false; 246 247 TRACE("%s(,0x%08lx,,%d)\n", __FUNCTION__, op, length); 248 249 switch (op) { 250 case TTYENABLE: 251 { 252 bool enable = *(bool *)buffer; 253 TRACE("TTYENABLE: %sable\n", enable ? "en" : "dis"); 254 255 if (enable) { 256 //XXX:must call SetModes(); 257 err = install_io_interrupt_handler(IRQ(), pc_serial_interrupt, this, 0); 258 TRACE("installing irq handler for %d: %s\n", IRQ(), strerror(err)); 259 } else { 260 // remove the handler 261 remove_io_interrupt_handler(IRQ(), pc_serial_interrupt, this); 262 // disable IRQ 263 WriteReg8(IER, 0); 264 WriteReg8(MCR, 0); 265 } 266 267 msr = ReadReg8(MSR); 268 269 SignalControlLineState(TTYHWDCD, msr & MSR_DCD); 270 SignalControlLineState(TTYHWCTS, msr & MSR_CTS); 271 272 if (enable) { 273 // 274 WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN /*| MCR_LOOP*//*XXXXXXX*/); 275 // enable irqs 276 WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); 277 //WriteReg8(IER, IER_RDA); 278 } 279 280 return true; 281 } 282 283 case TTYISTOP: 284 fInputStopped = *(bool *)buffer; 285 TRACE("TTYISTOP: %sstopped\n", fInputStopped ? "" : "not "); 286 287 if (fInputStopped) 288 MaskReg8(MCR, MCR_RTS); 289 else 290 OrReg8(MCR, MCR_RTS); 291 292 //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); 293 //SignalControlLineState(TTYHWCTS, !fInputStopped); 294 //msr = ReadReg8(MSR); 295 //SignalControlLineState(TTYHWCTS, msr & MSR_CTS); 296 return true; 297 298 case TTYGETSIGNALS: 299 TRACE("TTYGETSIGNALS\n"); 300 msr = ReadReg8(MSR); 301 SignalControlLineState(TTYHWDCD, msr & MSR_DCD); 302 SignalControlLineState(TTYHWCTS, msr & MSR_CTS); 303 SignalControlLineState(TTYHWDSR, msr & MSR_DSR); 304 SignalControlLineState(TTYHWRI, msr & MSR_RI); 305 return true; 306 307 case TTYSETMODES: 308 TRACE("TTYSETMODES\n"); 309 SetModes((struct termios *)buffer); 310 //WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); 311 return true; 312 313 case TTYSETDTR: 314 case TTYSETRTS: 315 { 316 bool set = *(bool *)buffer; 317 uint8 bit = TTYSETDTR ? MCR_DTR : MCR_RTS; 318 if (set) 319 OrReg8(MCR, bit); 320 else 321 MaskReg8(MCR, bit); 322 323 return true; 324 } 325 326 case TTYOSTART: 327 TRACE("TTYOSTART\n"); 328 // enable irqs 329 WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE); 330 return true; 331 case TTYOSYNC: 332 TRACE("TTYOSYNC\n"); 333 return (ReadReg8(LSR) & (LSR_THRE | LSR_TSRE)) == (LSR_THRE | LSR_TSRE); 334 return true; 335 case TTYSETBREAK: 336 { 337 bool set = *(bool *)buffer; 338 if (set) 339 OrReg8(MCR, LCR_BREAK); 340 else 341 MaskReg8(MCR, LCR_BREAK); 342 343 return true; 344 } 345 default: 346 return false; 347 } 348 349 return false; 350 } 351 352 353 #else /* __HAIKU__ */ 354 355 356 bool 357 SerialDevice::Service(struct tty *ptty, struct ddrover *ddr, uint flags) 358 { 359 uint8 msr; 360 status_t err; 361 362 if (&fTTY != ptty) 363 return false; 364 365 TRACE("%s(,,0x%08lx)\n", __FUNCTION__, flags); 366 367 switch (flags) { 368 case TTYENABLE: 369 TRACE("TTYENABLE\n"); 370 371 SetModes(); 372 err = install_io_interrupt_handler(IRQ(), pc_serial_interrupt, this, 0); 373 TRACE("installing irq handler for %d: %s\n", IRQ(), strerror(err)); 374 msr = ReadReg8(MSR); 375 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); 376 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); 377 // 378 WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN /*| MCR_LOOP*//*XXXXXXX*/); 379 // enable irqs 380 WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); 381 //WriteReg8(IER, IER_RDA); 382 break; 383 384 case TTYDISABLE: 385 TRACE("TTYDISABLE\n"); 386 // remove the handler 387 remove_io_interrupt_handler(IRQ(), pc_serial_interrupt, this); 388 // disable IRQ 389 WriteReg8(IER, 0); 390 WriteReg8(MCR, 0); 391 msr = ReadReg8(MSR); 392 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); 393 break; 394 395 case TTYISTOP: 396 TRACE("TTYISTOP\n"); 397 MaskReg8(MCR, MCR_RTS); 398 //fInputStopped = true; 399 //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); 400 break; 401 402 case TTYIRESUME: 403 TRACE("TTYIRESUME\n"); 404 OrReg8(MCR, MCR_RTS); 405 //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); 406 //fInputStopped = false; 407 break; 408 409 case TTYGETSIGNALS: 410 TRACE("TTYGETSIGNALS\n"); 411 msr = ReadReg8(MSR); 412 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); 413 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); 414 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDSR, msr & MSR_DSR); 415 gTTYModule->ttyhwsignal(ptty, ddr, TTYHWRI, msr & MSR_RI); 416 break; 417 418 case TTYSETMODES: 419 TRACE("TTYSETMODES\n"); 420 SetModes(); 421 //WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); 422 break; 423 424 case TTYOSTART: 425 TRACE("TTYOSTART\n"); 426 // enable irqs 427 WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE); 428 break; 429 case TTYOSYNC: 430 TRACE("TTYOSYNC\n"); 431 return (ReadReg8(LSR) & (LSR_THRE | LSR_TSRE)) == (LSR_THRE | LSR_TSRE); 432 break; 433 case TTYSETBREAK: 434 TRACE("TTYSETBREAK\n"); 435 OrReg8(LCR, LCR_BREAK); 436 break; 437 case TTYCLRBREAK: 438 TRACE("TTYCLRBREAK\n"); 439 MaskReg8(LCR, LCR_BREAK); 440 break; 441 case TTYSETDTR: 442 TRACE("TTYSETDTR\n"); 443 OrReg8(MCR, MCR_DTR); 444 break; 445 case TTYCLRDTR: 446 TRACE("TTYCLRDTR\n"); 447 MaskReg8(MCR, MCR_DTR); 448 break; 449 default: 450 return false; 451 } 452 453 return false; 454 } 455 #endif /* __HAIKU__ */ 456 457 458 int32 459 SerialDevice::InterruptHandler() 460 { 461 int32 ret = B_UNHANDLED_INTERRUPT; 462 #ifdef __HAIKU__ 463 //XXX: what should we do here ? (certainly not use a mutex !) 464 #else /* __HAIKU__ */ 465 gTTYModule->ddrstart(&fRover); 466 gTTYModule->ttyilock(&fTTY, &fRover, true); 467 #endif /* __HAIKU__ */ 468 469 uint8 iir, lsr, msr; 470 471 while (((iir = ReadReg8(IIR)) & IIR_PENDING) == 0) { // 0 means yes 472 int fifoavail = 1; 473 474 //DEBUG 475 // for (int count = 0; ReadReg8(LSR) & LSR_DR; count++) 476 // gTTYModule->ttyin(&fTTY, &fRover, ReadReg8(RBR)); 477 478 switch (iir & (IIR_IMASK | IIR_TO)) { 479 case IIR_THRE: 480 TRACE(("IIR_THRE\n")); 481 // check how much fifo we can use 482 //XXX: move to Init() ? 483 if ((iir & IIR_FMASK) == IIR_FMASK) 484 fifoavail = 16; 485 if (iir & IIR_F64EN) 486 fifoavail = 64; 487 for (int i = 0; i < fifoavail; i++) { 488 int chr; 489 #ifdef __HAIKU__ 490 chr = 'H';//XXX: what should we do here ? (certainly not call tty_read() !) 491 #else /* __HAIKU__ */ 492 chr = gTTYModule->ttyout(&fTTY, &fRover); 493 #endif /* __HAIKU__ */ 494 if (chr < 0) { 495 //WriteReg8(THB, (uint8)chr); 496 break; 497 } 498 WriteReg8(THB, (uint8)chr); 499 } 500 break; 501 case IIR_TO: 502 case IIR_TO | IIR_RDA: 503 // timeout: FALLTHROUGH 504 case IIR_RDA: 505 TRACE(("IIR_TO/RDA\n")); 506 // while data is ready... get it 507 while (ReadReg8(LSR) & LSR_DR) 508 #ifdef __HAIKU__ 509 ReadReg8(RBR);//XXX: what should we do here ? (certainly not call tty_write() !) 510 #else /* __HAIKU__ */ 511 gTTYModule->ttyin(&fTTY, &fRover, ReadReg8(RBR)); 512 #endif /* __HAIKU__ */ 513 break; 514 case IIR_RLS: 515 TRACE(("IIR_RLS\n")); 516 // ack 517 lsr = ReadReg8(LSR); 518 //XXX: handle this somehow 519 break; 520 case IIR_MS: 521 TRACE(("IIR_MS\n")); 522 // modem signals changed 523 msr = ReadReg8(MSR); 524 if (msr & MSR_DDCD) 525 SignalControlLineState(TTYHWDCD, msr & MSR_DCD); 526 if (msr & MSR_DCTS) 527 SignalControlLineState(TTYHWCTS, msr & MSR_CTS); 528 if (msr & MSR_DDSR) 529 SignalControlLineState(TTYHWDSR, msr & MSR_DSR); 530 if (msr & MSR_TERI) 531 SignalControlLineState(TTYHWRI, msr & MSR_RI); 532 break; 533 default: 534 TRACE(("IIR_?\n")); 535 // something happened 536 break; 537 } 538 ret = B_HANDLED_INTERRUPT; 539 TRACE(("IRQ:h\n")); 540 } 541 542 543 #ifdef __HAIKU__ 544 //XXX: what should we do here ? (certainly not use a mutex !) 545 #else /* __HAIKU__ */ 546 gTTYModule->ttyilock(&fTTY, &fRover, false); 547 gTTYModule->ddrdone(&fRover); 548 #endif /* __HAIKU__ */ 549 TRACE_FUNCRET("< IRQ:%d\n", ret); 550 return ret; 551 } 552 553 554 status_t 555 SerialDevice::Open(uint32 flags) 556 { 557 status_t status = B_OK; 558 559 if (fDeviceOpen) 560 return B_BUSY; 561 562 if (fDeviceRemoved) 563 return B_DEV_NOT_READY; 564 565 #ifdef __HAIKU__ 566 fMasterTTY = gTTYModule->tty_create(pc_serial_service, true); 567 if (fMasterTTY == NULL) { 568 TRACE_ALWAYS("open: failed to init master tty\n"); 569 return B_NO_MEMORY; 570 } 571 572 fSlaveTTY = gTTYModule->tty_create(NULL, false); 573 if (fSlaveTTY == NULL) { 574 TRACE_ALWAYS("open: failed to init slave tty\n"); 575 gTTYModule->tty_destroy(fMasterTTY); 576 return B_NO_MEMORY; 577 } 578 579 fTTYCookie = gTTYModule->tty_create_cookie(fMasterTTY, fSlaveTTY, flags); 580 if (fTTYCookie == NULL) { 581 TRACE_ALWAYS("open: failed to init tty cookie\n"); 582 gTTYModule->tty_destroy(fMasterTTY); 583 gTTYModule->tty_destroy(fSlaveTTY); 584 return B_NO_MEMORY; 585 } 586 587 ResetDevice(); 588 589 #else /* __HAIKU__ */ 590 591 gTTYModule->ttyinit(&fTTY, false); 592 fTTYFile.tty = &fTTY; 593 fTTYFile.flags = flags; 594 595 596 ResetDevice(); 597 598 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 599 if (!ddr) 600 return B_NO_MEMORY; 601 602 gTTYModule->ddacquire(ddr, &gSerialDomain); 603 status = gTTYModule->ttyopen(&fTTYFile, ddr, pc_serial_service); 604 gTTYModule->ddrdone(ddr); 605 606 #endif /* __HAIKU__ */ 607 608 if (status < B_OK) { 609 TRACE_ALWAYS("open: failed to open tty\n"); 610 return status; 611 } 612 613 #if 0 614 fDeviceThread = spawn_kernel_thread(DeviceThread, "usb_serial device thread", 615 B_NORMAL_PRIORITY, this); 616 617 if (fDeviceThread < B_OK) { 618 TRACE_ALWAYS("open: failed to spawn kernel thread\n"); 619 return fDeviceThread; 620 } 621 622 resume_thread(fDeviceThread); 623 624 fControlOut = CLS_LINE_DTR | CLS_LINE_RTS; 625 SetControlLineState(fControlOut); 626 627 status = gUSBModule->queue_interrupt(fControlPipe, fInterruptBuffer, 628 fInterruptBufferSize, InterruptCallbackFunction, this); 629 if (status < B_OK) 630 TRACE_ALWAYS("failed to queue initial interrupt\n"); 631 632 #endif 633 fDeviceOpen = true; 634 return B_OK; 635 } 636 637 638 status_t 639 SerialDevice::Read(char *buffer, size_t *numBytes) 640 { 641 if (fDeviceRemoved) { 642 *numBytes = 0; 643 return B_DEV_NOT_READY; 644 } 645 646 status_t status; 647 648 #ifdef __HAIKU__ 649 650 status = mutex_lock(&fReadLock); 651 if (status != B_OK) { 652 TRACE_ALWAYS("read: failed to get read lock\n"); 653 *numBytes = 0; 654 return status; 655 } 656 657 status = gTTYModule->tty_read(fTTYCookie, buffer, numBytes); 658 659 mutex_unlock(&fReadLock); 660 661 #else /* __HAIKU__ */ 662 663 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 664 if (!ddr) { 665 *numBytes = 0; 666 return B_NO_MEMORY; 667 } 668 669 status = gTTYModule->ttyread(&fTTYFile, ddr, buffer, numBytes); 670 gTTYModule->ddrdone(ddr); 671 672 #endif /* __HAIKU__ */ 673 674 return status; 675 } 676 677 678 status_t 679 SerialDevice::Write(const char *buffer, size_t *numBytes) 680 { 681 //size_t bytesLeft = *numBytes; 682 //*numBytes = 0; 683 684 status_t status = EINVAL; 685 686 #ifdef __HAIKU__ 687 688 status = mutex_lock(&fWriteLock); 689 if (status != B_OK) { 690 TRACE_ALWAYS("write: failed to get write lock\n"); 691 return status; 692 } 693 694 //XXX: WTF tty_write() is not for write() hook ? 695 //status = gTTYModule->tty_write(fTTYCookie, buffer, numBytes); 696 mutex_unlock(&fWriteLock); 697 698 #else /* __HAIKU__ */ 699 700 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 701 if (!ddr) { 702 *numBytes = 0; 703 return B_ERROR; 704 } 705 706 status = gTTYModule->ttywrite(&fTTYFile, ddr, buffer, numBytes); 707 gTTYModule->ddrdone(ddr); 708 709 #endif /* __HAIKU__ */ 710 711 #if 0 712 status_t status = mutex_lock(&fWriteLock); 713 if (status != B_OK) { 714 TRACE_ALWAYS("write: failed to get write lock\n"); 715 return status; 716 } 717 718 if (fDeviceRemoved) { 719 mutex_unlock(&fWriteLock); 720 return B_DEV_NOT_READY; 721 } 722 723 while (bytesLeft > 0) { 724 size_t length = MIN(bytesLeft, fWriteBufferSize); 725 size_t packetLength = length; 726 OnWrite(buffer, &length, &packetLength); 727 728 status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, 729 packetLength, WriteCallbackFunction, this); 730 if (status < B_OK) { 731 TRACE_ALWAYS("write: queueing failed with status 0x%08x\n", status); 732 break; 733 } 734 735 status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0); 736 if (status < B_OK) { 737 TRACE_ALWAYS("write: failed to get write done sem 0x%08x\n", status); 738 break; 739 } 740 741 if (fStatusWrite != B_OK) { 742 TRACE("write: device status error 0x%08x\n", fStatusWrite); 743 status = gUSBModule->clear_feature(fWritePipe, 744 USB_FEATURE_ENDPOINT_HALT); 745 if (status < B_OK) { 746 TRACE_ALWAYS("write: failed to clear device halt\n"); 747 status = B_ERROR; 748 break; 749 } 750 continue; 751 } 752 753 buffer += length; 754 *numBytes += length; 755 bytesLeft -= length; 756 } 757 758 mutex_unlock(&fWriteLock); 759 #endif 760 return status; 761 } 762 763 764 status_t 765 SerialDevice::Control(uint32 op, void *arg, size_t length) 766 { 767 status_t status = B_OK; 768 769 if (fDeviceRemoved) 770 return B_DEV_NOT_READY; 771 772 #ifdef __HAIKU__ 773 774 status = gTTYModule->tty_control(fTTYCookie, op, arg, length); 775 776 #else /* __HAIKU__ */ 777 778 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 779 if (!ddr) 780 return B_NO_MEMORY; 781 782 status = gTTYModule->ttycontrol(&fTTYFile, ddr, op, arg, length); 783 gTTYModule->ddrdone(ddr); 784 785 #endif /* __HAIKU__ */ 786 787 return status; 788 } 789 790 791 status_t 792 SerialDevice::Select(uint8 event, uint32 ref, selectsync *sync) 793 { 794 if (fDeviceRemoved) 795 return B_DEV_NOT_READY; 796 797 #ifdef __HAIKU__ 798 799 return gTTYModule->tty_select(fTTYCookie, event, ref, sync); 800 801 #else /* __HAIKU__ */ 802 803 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 804 if (!ddr) 805 return B_NO_MEMORY; 806 807 status_t status = gTTYModule->ttyselect(&fTTYFile, ddr, event, ref, sync); 808 gTTYModule->ddrdone(ddr); 809 810 return status; 811 812 #endif /* __HAIKU__ */ 813 } 814 815 816 status_t 817 SerialDevice::DeSelect(uint8 event, selectsync *sync) 818 { 819 if (fDeviceRemoved) 820 return B_DEV_NOT_READY; 821 822 #ifdef __HAIKU__ 823 824 return gTTYModule->tty_deselect(fTTYCookie, event, sync); 825 826 #else /* __HAIKU__ */ 827 828 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 829 if (!ddr) 830 return B_NO_MEMORY; 831 832 status_t status = gTTYModule->ttydeselect(&fTTYFile, ddr, event, sync); 833 gTTYModule->ddrdone(ddr); 834 835 return status; 836 837 #endif /* __HAIKU__ */ 838 } 839 840 841 status_t 842 SerialDevice::Close() 843 { 844 status_t status = B_OK; 845 846 OnClose(); 847 848 if (!fDeviceRemoved) { 849 #if 0 850 gUSBModule->cancel_queued_transfers(fReadPipe); 851 gUSBModule->cancel_queued_transfers(fWritePipe); 852 gUSBModule->cancel_queued_transfers(fControlPipe); 853 #endif 854 } 855 856 #ifdef __HAIKU__ 857 gTTYModule->tty_destroy_cookie(fTTYCookie); 858 #else /* __HAIKU__ */ 859 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 860 if (!ddr) 861 return B_NO_MEMORY; 862 863 status = gTTYModule->ttyclose(&fTTYFile, ddr); 864 gTTYModule->ddrdone(ddr); 865 866 #endif /* __HAIKU__ */ 867 868 fDeviceOpen = false; 869 return status; 870 } 871 872 873 status_t 874 SerialDevice::Free() 875 { 876 status_t status = B_OK; 877 #ifdef __HAIKU__ 878 gTTYModule->tty_destroy(fMasterTTY); 879 gTTYModule->tty_destroy(fSlaveTTY); 880 #else /* __HAIKU__ */ 881 struct ddrover *ddr = gTTYModule->ddrstart(NULL); 882 if (!ddr) 883 return B_NO_MEMORY; 884 885 status = gTTYModule->ttyfree(&fTTYFile, ddr); 886 gTTYModule->ddrdone(ddr); 887 #endif /* __HAIKU__ */ 888 return status; 889 } 890 891 892 void 893 SerialDevice::Removed() 894 { 895 if (fDeviceRemoved) 896 return; 897 898 // notifies us that the device was removed 899 fDeviceRemoved = true; 900 901 // we need to ensure that we do not use the device anymore 902 fStopDeviceThread = true; 903 fInputStopped = false; 904 #if 0 905 gUSBModule->cancel_queued_transfers(fReadPipe); 906 gUSBModule->cancel_queued_transfers(fWritePipe); 907 gUSBModule->cancel_queued_transfers(fControlPipe); 908 #endif 909 910 //int32 result = B_OK; 911 //wait_for_thread(fDeviceThread, &result); 912 fDeviceThread = -1; 913 914 mutex_lock(&fWriteLock); 915 mutex_unlock(&fWriteLock); 916 } 917 918 919 status_t 920 SerialDevice::AddDevice(const serial_config_descriptor *config) 921 { 922 // default implementation - does nothing 923 return B_ERROR; 924 } 925 926 927 status_t 928 SerialDevice::ResetDevice() 929 { 930 // default implementation - does nothing 931 return B_OK; 932 } 933 934 935 #if 0 936 status_t 937 SerialDevice::SetLineCoding(usb_serial_line_coding *coding) 938 { 939 // default implementation - does nothing 940 return B_OK; 941 } 942 #endif 943 944 status_t 945 SerialDevice::SignalControlLineState(int line, bool enable) 946 { 947 #ifdef __HAIKU__ 948 gTTYModule->tty_hardware_signal(fTTYCookie, line, enable); 949 #else 950 // XXX: only works for interrupt handler, Service func must pass the ddrover 951 gTTYModule->ttyhwsignal(&fTTY, &fRover, line, enable); 952 #endif 953 return B_OK; 954 } 955 956 957 void 958 SerialDevice::OnRead(char **buffer, size_t *numBytes) 959 { 960 // default implementation - does nothing 961 } 962 963 964 void 965 SerialDevice::OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes) 966 { 967 // default implementation - does nothing 968 } 969 970 971 void 972 SerialDevice::OnClose() 973 { 974 // default implementation - does nothing 975 } 976 977 978 int32 979 SerialDevice::DeviceThread(void *data) 980 { 981 #if 0 982 SerialDevice *device = (SerialDevice *)data; 983 984 while (!device->fStopDeviceThread) { 985 status_t status = gUSBModule->queue_bulk(device->fReadPipe, 986 device->fReadBuffer, device->fReadBufferSize, 987 device->ReadCallbackFunction, data); 988 if (status < B_OK) { 989 TRACE_ALWAYS("device thread: queueing failed with error: 0x%08x\n", status); 990 break; 991 } 992 993 status = acquire_sem_etc(device->fDoneRead, 1, B_CAN_INTERRUPT, 0); 994 if (status < B_OK) { 995 TRACE_ALWAYS("device thread: failed to get read done sem 0x%08x\n", status); 996 break; 997 } 998 999 if (device->fStatusRead != B_OK) { 1000 TRACE("device thread: device status error 0x%08x\n", 1001 device->fStatusRead); 1002 if (gUSBModule->clear_feature(device->fReadPipe, 1003 USB_FEATURE_ENDPOINT_HALT) != B_OK) { 1004 TRACE_ALWAYS("device thread: failed to clear halt feature\n"); 1005 break; 1006 } 1007 } 1008 1009 char *buffer = device->fReadBuffer; 1010 size_t readLength = device->fActualLengthRead; 1011 device->OnRead(&buffer, &readLength); 1012 if (readLength == 0) 1013 continue; 1014 1015 ddrover *ddr = gTTYModule->ddrstart(NULL); 1016 if (!ddr) { 1017 TRACE_ALWAYS("device thread: ddrstart problem\n"); 1018 return B_NO_MEMORY; 1019 } 1020 1021 while (device->fInputStopped) 1022 snooze(100); 1023 1024 gTTYModule->ttyilock(&device->fTTY, ddr, true); 1025 for (size_t i = 0; i < readLength; i++) 1026 gTTYModule->ttyin(&device->fTTY, ddr, buffer[i]); 1027 1028 gTTYModule->ttyilock(&device->fTTY, ddr, false); 1029 gTTYModule->ddrdone(ddr); 1030 } 1031 1032 #endif 1033 return B_OK; 1034 } 1035 1036 1037 void 1038 SerialDevice::ReadCallbackFunction(void *cookie, int32 status, void *data, 1039 uint32 actualLength) 1040 { 1041 TRACE_FUNCALLS("read callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 1042 cookie, status, data, actualLength); 1043 1044 SerialDevice *device = (SerialDevice *)cookie; 1045 device->fActualLengthRead = actualLength; 1046 device->fStatusRead = status; 1047 release_sem_etc(device->fDoneRead, 1, B_DO_NOT_RESCHEDULE); 1048 } 1049 1050 1051 void 1052 SerialDevice::WriteCallbackFunction(void *cookie, int32 status, void *data, 1053 uint32 actualLength) 1054 { 1055 TRACE_FUNCALLS("write callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 1056 cookie, status, data, actualLength); 1057 1058 SerialDevice *device = (SerialDevice *)cookie; 1059 device->fActualLengthWrite = actualLength; 1060 device->fStatusWrite = status; 1061 release_sem_etc(device->fDoneWrite, 1, B_DO_NOT_RESCHEDULE); 1062 } 1063 1064 1065 void 1066 SerialDevice::InterruptCallbackFunction(void *cookie, int32 status, 1067 void *data, uint32 actualLength) 1068 { 1069 TRACE_FUNCALLS("interrupt callback: cookie: 0x%08x status: 0x%08x data: 0x%08x len: %lu\n", 1070 cookie, status, data, actualLength); 1071 1072 SerialDevice *device = (SerialDevice *)cookie; 1073 device->fActualLengthInterrupt = actualLength; 1074 device->fStatusInterrupt = status; 1075 1076 // ToDo: maybe handle those somehow? 1077 1078 if (status == B_OK && !device->fDeviceRemoved) { 1079 #if 0 1080 status = gUSBModule->queue_interrupt(device->fControlPipe, 1081 device->fInterruptBuffer, device->fInterruptBufferSize, 1082 device->InterruptCallbackFunction, device); 1083 #endif 1084 } 1085 } 1086 1087 1088 1089 #if 0 1090 SerialDevice * 1091 SerialDevice::MakeDevice(usb_device device, uint16 vendorID, 1092 uint16 productID) 1093 { 1094 const char *description = NULL; 1095 1096 switch (vendorID) { 1097 case VENDOR_IODATA: 1098 case VENDOR_ATEN: 1099 case VENDOR_TDK: 1100 case VENDOR_RATOC: 1101 case VENDOR_PROLIFIC: 1102 case VENDOR_ELECOM: 1103 case VENDOR_SOURCENEXT: 1104 case VENDOR_HAL: 1105 { 1106 switch (productID) { 1107 case PRODUCT_PROLIFIC_RSAQ2: description = "PL2303 Serial adapter (IODATA USB-RSAQ2)"; break; 1108 case PRODUCT_IODATA_USBRSAQ: description = "I/O Data USB serial adapter USB-RSAQ1"; break; 1109 case PRODUCT_ATEN_UC232A: description = "Aten Serial adapter"; break; 1110 case PRODUCT_TDK_UHA6400: description = "TDK USB-PHS Adapter UHA6400"; break; 1111 case PRODUCT_RATOC_REXUSB60: description = "Ratoc USB serial adapter REX-USB60"; break; 1112 case PRODUCT_PROLIFIC_PL2303: description = "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"; break; 1113 case PRODUCT_ELECOM_UCSGT: description = "Elecom UC-SGT"; break; 1114 case PRODUCT_SOURCENEXT_KEIKAI8: description = "SOURCENEXT KeikaiDenwa 8"; break; 1115 case PRODUCT_SOURCENEXT_KEIKAI8_CHG: description = "SOURCENEXT KeikaiDenwa 8 with charger"; break; 1116 case PRODUCT_HAL_IMR001: description = "HAL Corporation Crossam2+USB"; break; 1117 } 1118 1119 if (!description) 1120 break; 1121 1122 return new(std::nothrow) ProlificDevice(device, vendorID, productID, description); 1123 } 1124 1125 case VENDOR_FTDI: 1126 { 1127 switch (productID) { 1128 case PRODUCT_FTDI_8U100AX: description = "FTDI 8U100AX serial converter"; break; 1129 case PRODUCT_FTDI_8U232AM: description = "FTDI 8U232AM serial converter"; break; 1130 } 1131 1132 if (!description) 1133 break; 1134 1135 return new(std::nothrow) FTDIDevice(device, vendorID, productID, description); 1136 } 1137 1138 case VENDOR_PALM: 1139 case VENDOR_KLSI: 1140 { 1141 switch (productID) { 1142 case PRODUCT_PALM_CONNECT: description = "PalmConnect RS232"; break; 1143 case PRODUCT_KLSI_KL5KUSB105D: description = "KLSI KL5KUSB105D"; break; 1144 } 1145 1146 if (!description) 1147 break; 1148 1149 return new(std::nothrow) KLSIDevice(device, vendorID, productID, description); 1150 } 1151 } 1152 1153 return new(std::nothrow) ACMDevice(device, vendorID, productID, "CDC ACM compatible device"); 1154 } 1155 #endif 1156 1157 1158 uint8 1159 SerialDevice::ReadReg8(int reg) 1160 { 1161 uint8 ret; 1162 switch (fBus) { 1163 case B_ISA_BUS: 1164 ret = gISAModule->read_io_8(IOBase() + reg); 1165 break; 1166 case B_PCI_BUS: 1167 ret = gPCIModule->read_io_8(IOBase() + reg); 1168 break; 1169 default: 1170 TRACE_ALWAYS("%s: unknown bus!\n", __FUNCTION__); 1171 ret = 0; 1172 //XXX:pcmcia ? 1173 } 1174 TRACE/*_ALWAYS*/("RR8(%d) = %d [%02x]\n", reg, ret, ret); 1175 //spin(1000); 1176 return ret; 1177 } 1178 1179 void 1180 SerialDevice::WriteReg8(int reg, uint8 value) 1181 { 1182 // TRACE_ALWAYS("WR8(0x%04x+%d, %d [0x%x])\n", IOBase(), reg, value, value); 1183 TRACE/*_ALWAYS*/("WR8(%d, %d [0x%x])\n", reg, value, value); 1184 switch (fBus) { 1185 case B_ISA_BUS: 1186 gISAModule->write_io_8(IOBase() + reg, value); 1187 break; 1188 case B_PCI_BUS: 1189 gPCIModule->write_io_8(IOBase() + reg, value); 1190 break; 1191 default: 1192 TRACE_ALWAYS("%s: unknown bus!\n", __FUNCTION__); 1193 //XXX:pcmcia ? 1194 } 1195 //spin(10000); 1196 } 1197 1198 1199 void 1200 SerialDevice::OrReg8(int reg, uint8 value) 1201 { 1202 WriteReg8(reg, ReadReg8(reg) | value); 1203 } 1204 1205 1206 void 1207 SerialDevice::AndReg8(int reg, uint8 value) 1208 { 1209 WriteReg8(reg, ReadReg8(reg) & value); 1210 } 1211 1212 1213 void 1214 SerialDevice::MaskReg8(int reg, uint8 value) 1215 { 1216 WriteReg8(reg, ReadReg8(reg) & ~value); 1217 } 1218