umct.c (187970) | umct.c (188413) |
---|---|
1#include <sys/cdefs.h> | 1#include <sys/cdefs.h> |
2__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/umct2.c 187970 2009-02-01 00:51:25Z thompsa $"); | 2__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/umct2.c 188413 2009-02-09 22:05:25Z thompsa $"); |
3 4/*- 5 * Copyright (c) 2003 Scott Long 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: --- 67 unchanged lines hidden (view full) --- 78 79#define UMCT_INTR_INTERVAL 100 80#define UMCT_IFACE_INDEX 0 81#define UMCT_CONFIG_INDEX 1 82 83enum { 84 UMCT_BULK_DT_WR, 85 UMCT_BULK_DT_RD, | 3 4/*- 5 * Copyright (c) 2003 Scott Long 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: --- 67 unchanged lines hidden (view full) --- 78 79#define UMCT_INTR_INTERVAL 100 80#define UMCT_IFACE_INDEX 0 81#define UMCT_CONFIG_INDEX 1 82 83enum { 84 UMCT_BULK_DT_WR, 85 UMCT_BULK_DT_RD, |
86 UMCT_BULK_CS_WR, 87 UMCT_BULK_CS_RD, | |
88 UMCT_INTR_DT_RD, | 86 UMCT_INTR_DT_RD, |
89 UMCT_INTR_CS_RD, 90 UMCT_N_TRANSFER = 6, | 87 UMCT_N_TRANSFER, |
91}; 92 93struct umct_softc { 94 struct usb2_com_super_softc sc_super_ucom; 95 struct usb2_com_softc sc_ucom; 96 97 struct usb2_device *sc_udev; 98 struct usb2_xfer *sc_xfer[UMCT_N_TRANSFER]; 99 100 uint32_t sc_unit; 101 102 uint16_t sc_obufsize; 103 104 uint8_t sc_lsr; 105 uint8_t sc_msr; 106 uint8_t sc_lcr; 107 uint8_t sc_mcr; | 88}; 89 90struct umct_softc { 91 struct usb2_com_super_softc sc_super_ucom; 92 struct usb2_com_softc sc_ucom; 93 94 struct usb2_device *sc_udev; 95 struct usb2_xfer *sc_xfer[UMCT_N_TRANSFER]; 96 97 uint32_t sc_unit; 98 99 uint16_t sc_obufsize; 100 101 uint8_t sc_lsr; 102 uint8_t sc_msr; 103 uint8_t sc_lcr; 104 uint8_t sc_mcr; |
108 109 uint8_t sc_name[16]; 110 uint8_t sc_flags; 111#define UMCT_FLAG_READ_STALL 0x01 112#define UMCT_FLAG_WRITE_STALL 0x02 113#define UMCT_FLAG_INTR_STALL 0x04 | |
114 uint8_t sc_iface_no; | 105 uint8_t sc_iface_no; |
106 uint8_t sc_name[16]; |
|
115}; 116 117/* prototypes */ 118 119static device_probe_t umct_probe; 120static device_attach_t umct_attach; 121static device_detach_t umct_detach; 122 | 107}; 108 109/* prototypes */ 110 111static device_probe_t umct_probe; 112static device_attach_t umct_attach; 113static device_detach_t umct_detach; 114 |
123static usb2_callback_t umct_intr_clear_stall_callback; | |
124static usb2_callback_t umct_intr_callback; 125static usb2_callback_t umct_write_callback; | 115static usb2_callback_t umct_intr_callback; 116static usb2_callback_t umct_write_callback; |
126static usb2_callback_t umct_write_clear_stall_callback; | |
127static usb2_callback_t umct_read_callback; | 117static usb2_callback_t umct_read_callback; |
128static usb2_callback_t umct_read_clear_stall_callback; | |
129 | 118 |
130static void umct_cfg_do_request(struct umct_softc *, uint8_t, uint16_t, 131 uint32_t); | 119static void umct_cfg_do_request(struct umct_softc *sc, uint8_t request, 120 uint16_t len, uint32_t value); |
132static void umct_cfg_get_status(struct usb2_com_softc *, uint8_t *, 133 uint8_t *); 134static void umct_cfg_set_break(struct usb2_com_softc *, uint8_t); 135static void umct_cfg_set_dtr(struct usb2_com_softc *, uint8_t); 136static void umct_cfg_set_rts(struct usb2_com_softc *, uint8_t); 137static uint8_t umct_calc_baud(uint32_t); 138static int umct_pre_param(struct usb2_com_softc *, struct termios *); 139static void umct_cfg_param(struct usb2_com_softc *, struct termios *); --- 18 unchanged lines hidden (view full) --- 158 .endpoint = UE_ADDR_ANY, 159 .direction = UE_DIR_IN, 160 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 161 .mh.bufsize = 0, /* use wMaxPacketSize */ 162 .mh.callback = &umct_read_callback, 163 .ep_index = 0, /* first interrupt endpoint */ 164 }, 165 | 121static void umct_cfg_get_status(struct usb2_com_softc *, uint8_t *, 122 uint8_t *); 123static void umct_cfg_set_break(struct usb2_com_softc *, uint8_t); 124static void umct_cfg_set_dtr(struct usb2_com_softc *, uint8_t); 125static void umct_cfg_set_rts(struct usb2_com_softc *, uint8_t); 126static uint8_t umct_calc_baud(uint32_t); 127static int umct_pre_param(struct usb2_com_softc *, struct termios *); 128static void umct_cfg_param(struct usb2_com_softc *, struct termios *); --- 18 unchanged lines hidden (view full) --- 147 .endpoint = UE_ADDR_ANY, 148 .direction = UE_DIR_IN, 149 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 150 .mh.bufsize = 0, /* use wMaxPacketSize */ 151 .mh.callback = &umct_read_callback, 152 .ep_index = 0, /* first interrupt endpoint */ 153 }, 154 |
166 [UMCT_BULK_CS_WR] = { 167 .type = UE_CONTROL, 168 .endpoint = 0x00, /* Control pipe */ 169 .direction = UE_DIR_ANY, 170 .mh.bufsize = sizeof(struct usb2_device_request), 171 .mh.flags = {}, 172 .mh.callback = &umct_write_clear_stall_callback, 173 .mh.timeout = 1000, /* 1 second */ 174 .mh.interval = 50, /* 50ms */ 175 }, 176 177 [UMCT_BULK_CS_RD] = { 178 .type = UE_CONTROL, 179 .endpoint = 0x00, /* Control pipe */ 180 .direction = UE_DIR_ANY, 181 .mh.bufsize = sizeof(struct usb2_device_request), 182 .mh.flags = {}, 183 .mh.callback = &umct_read_clear_stall_callback, 184 .mh.timeout = 1000, /* 1 second */ 185 .mh.interval = 50, /* 50ms */ 186 }, 187 | |
188 [UMCT_INTR_DT_RD] = { 189 .type = UE_INTERRUPT, 190 .endpoint = UE_ADDR_ANY, 191 .direction = UE_DIR_IN, 192 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 193 .mh.bufsize = 0, /* use wMaxPacketSize */ 194 .mh.callback = &umct_intr_callback, 195 .ep_index = 1, /* second interrupt endpoint */ 196 }, | 155 [UMCT_INTR_DT_RD] = { 156 .type = UE_INTERRUPT, 157 .endpoint = UE_ADDR_ANY, 158 .direction = UE_DIR_IN, 159 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 160 .mh.bufsize = 0, /* use wMaxPacketSize */ 161 .mh.callback = &umct_intr_callback, 162 .ep_index = 1, /* second interrupt endpoint */ 163 }, |
197 198 [UMCT_INTR_CS_RD] = { 199 .type = UE_CONTROL, 200 .endpoint = 0x00, /* Control pipe */ 201 .direction = UE_DIR_ANY, 202 .mh.bufsize = sizeof(struct usb2_device_request), 203 .mh.flags = {}, 204 .mh.callback = &umct_intr_clear_stall_callback, 205 .mh.timeout = 1000, /* 1 second */ 206 .mh.interval = 50, /* 50ms */ 207 }, | |
208}; 209 210static const struct usb2_com_callback umct_callback = { 211 .usb2_com_cfg_get_status = &umct_cfg_get_status, 212 .usb2_com_cfg_set_dtr = &umct_cfg_set_dtr, 213 .usb2_com_cfg_set_rts = &umct_cfg_set_rts, 214 .usb2_com_cfg_set_break = &umct_cfg_set_break, 215 .usb2_com_cfg_param = &umct_cfg_param, --- 128 unchanged lines hidden (view full) --- 344static void 345umct_cfg_do_request(struct umct_softc *sc, uint8_t request, 346 uint16_t len, uint32_t value) 347{ 348 struct usb2_device_request req; 349 usb2_error_t err; 350 uint8_t temp[4]; 351 | 164}; 165 166static const struct usb2_com_callback umct_callback = { 167 .usb2_com_cfg_get_status = &umct_cfg_get_status, 168 .usb2_com_cfg_set_dtr = &umct_cfg_set_dtr, 169 .usb2_com_cfg_set_rts = &umct_cfg_set_rts, 170 .usb2_com_cfg_set_break = &umct_cfg_set_break, 171 .usb2_com_cfg_param = &umct_cfg_param, --- 128 unchanged lines hidden (view full) --- 300static void 301umct_cfg_do_request(struct umct_softc *sc, uint8_t request, 302 uint16_t len, uint32_t value) 303{ 304 struct usb2_device_request req; 305 usb2_error_t err; 306 uint8_t temp[4]; 307 |
352 if (usb2_com_cfg_is_gone(&sc->sc_ucom)) { 353 goto done; 354 } 355 if (len > 4) { | 308 if (len > 4) |
356 len = 4; | 309 len = 4; |
357 } | |
358 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 359 req.bRequest = request; 360 USETW(req.wValue, 0); 361 req.wIndex[0] = sc->sc_iface_no; 362 req.wIndex[1] = 0; 363 USETW(req.wLength, len); 364 USETDW(temp, value); 365 | 310 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 311 req.bRequest = request; 312 USETW(req.wValue, 0); 313 req.wIndex[0] = sc->sc_iface_no; 314 req.wIndex[1] = 0; 315 USETW(req.wLength, len); 316 USETDW(temp, value); 317 |
366 err = usb2_do_request_flags(sc->sc_udev, &Giant, &req, 367 temp, 0, NULL, 1000); 368 | 318 err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 319 &req, temp, 0, 1000); |
369 if (err) { 370 DPRINTFN(0, "device request failed, err=%s " 371 "(ignored)\n", usb2_errstr(err)); 372 } | 320 if (err) { 321 DPRINTFN(0, "device request failed, err=%s " 322 "(ignored)\n", usb2_errstr(err)); 323 } |
373done: | |
374 return; 375} 376 377static void | 324 return; 325} 326 327static void |
378umct_intr_clear_stall_callback(struct usb2_xfer *xfer) 379{ 380 struct umct_softc *sc = xfer->priv_sc; 381 struct usb2_xfer *xfer_other = sc->sc_xfer[UMCT_INTR_DT_RD]; 382 383 if (usb2_clear_stall_callback(xfer, xfer_other)) { 384 DPRINTF("stall cleared\n"); 385 sc->sc_flags &= ~UMCT_FLAG_INTR_STALL; 386 usb2_transfer_start(xfer_other); 387 } 388} 389 390static void | |
391umct_intr_callback(struct usb2_xfer *xfer) 392{ 393 struct umct_softc *sc = xfer->priv_sc; 394 uint8_t buf[2]; 395 396 switch (USB_GET_STATE(xfer)) { 397 case USB_ST_TRANSFERRED: 398 if (xfer->actlen < 2) { --- 4 unchanged lines hidden (view full) --- 403 404 sc->sc_msr = buf[0]; 405 sc->sc_lsr = buf[1]; 406 407 usb2_com_status_change(&sc->sc_ucom); 408 409 case USB_ST_SETUP: 410tr_setup: | 328umct_intr_callback(struct usb2_xfer *xfer) 329{ 330 struct umct_softc *sc = xfer->priv_sc; 331 uint8_t buf[2]; 332 333 switch (USB_GET_STATE(xfer)) { 334 case USB_ST_TRANSFERRED: 335 if (xfer->actlen < 2) { --- 4 unchanged lines hidden (view full) --- 340 341 sc->sc_msr = buf[0]; 342 sc->sc_lsr = buf[1]; 343 344 usb2_com_status_change(&sc->sc_ucom); 345 346 case USB_ST_SETUP: 347tr_setup: |
411 if (sc->sc_flags & UMCT_FLAG_INTR_STALL) { 412 usb2_transfer_start(sc->sc_xfer[UMCT_INTR_CS_RD]); 413 } else { 414 xfer->frlengths[0] = xfer->max_data_length; 415 usb2_start_hardware(xfer); 416 } | 348 xfer->frlengths[0] = xfer->max_data_length; 349 usb2_start_hardware(xfer); |
417 return; 418 419 default: /* Error */ 420 if (xfer->error != USB_ERR_CANCELLED) { | 350 return; 351 352 default: /* Error */ 353 if (xfer->error != USB_ERR_CANCELLED) { |
421 /* start clear stall */ 422 sc->sc_flags |= UMCT_FLAG_INTR_STALL; 423 usb2_transfer_start(sc->sc_xfer[UMCT_INTR_CS_RD]); | 354 /* try to clear stall first */ 355 xfer->flags.stall_pipe = 1; 356 goto tr_setup; |
424 } 425 return; | 357 } 358 return; |
426 | |
427 } 428} 429 430static void 431umct_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr) 432{ 433 struct umct_softc *sc = ucom->sc_parent; 434 --- 130 unchanged lines hidden (view full) --- 565} 566 567static void 568umct_stop_read(struct usb2_com_softc *ucom) 569{ 570 struct umct_softc *sc = ucom->sc_parent; 571 572 /* stop interrupt endpoint */ | 359 } 360} 361 362static void 363umct_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr) 364{ 365 struct umct_softc *sc = ucom->sc_parent; 366 --- 130 unchanged lines hidden (view full) --- 497} 498 499static void 500umct_stop_read(struct usb2_com_softc *ucom) 501{ 502 struct umct_softc *sc = ucom->sc_parent; 503 504 /* stop interrupt endpoint */ |
573 usb2_transfer_stop(sc->sc_xfer[UMCT_INTR_CS_RD]); | |
574 usb2_transfer_stop(sc->sc_xfer[UMCT_INTR_DT_RD]); 575 576 /* stop read endpoint */ | 505 usb2_transfer_stop(sc->sc_xfer[UMCT_INTR_DT_RD]); 506 507 /* stop read endpoint */ |
577 usb2_transfer_stop(sc->sc_xfer[UMCT_BULK_CS_RD]); | |
578 usb2_transfer_stop(sc->sc_xfer[UMCT_BULK_DT_RD]); 579} 580 581static void 582umct_start_write(struct usb2_com_softc *ucom) 583{ 584 struct umct_softc *sc = ucom->sc_parent; 585 586 usb2_transfer_start(sc->sc_xfer[UMCT_BULK_DT_WR]); 587} 588 589static void 590umct_stop_write(struct usb2_com_softc *ucom) 591{ 592 struct umct_softc *sc = ucom->sc_parent; 593 | 508 usb2_transfer_stop(sc->sc_xfer[UMCT_BULK_DT_RD]); 509} 510 511static void 512umct_start_write(struct usb2_com_softc *ucom) 513{ 514 struct umct_softc *sc = ucom->sc_parent; 515 516 usb2_transfer_start(sc->sc_xfer[UMCT_BULK_DT_WR]); 517} 518 519static void 520umct_stop_write(struct usb2_com_softc *ucom) 521{ 522 struct umct_softc *sc = ucom->sc_parent; 523 |
594 usb2_transfer_stop(sc->sc_xfer[UMCT_BULK_CS_WR]); | |
595 usb2_transfer_stop(sc->sc_xfer[UMCT_BULK_DT_WR]); 596} 597 598static void 599umct_write_callback(struct usb2_xfer *xfer) 600{ 601 struct umct_softc *sc = xfer->priv_sc; 602 uint32_t actlen; 603 604 switch (USB_GET_STATE(xfer)) { 605 case USB_ST_SETUP: 606 case USB_ST_TRANSFERRED: | 524 usb2_transfer_stop(sc->sc_xfer[UMCT_BULK_DT_WR]); 525} 526 527static void 528umct_write_callback(struct usb2_xfer *xfer) 529{ 530 struct umct_softc *sc = xfer->priv_sc; 531 uint32_t actlen; 532 533 switch (USB_GET_STATE(xfer)) { 534 case USB_ST_SETUP: 535 case USB_ST_TRANSFERRED: |
607 if (sc->sc_flags & UMCT_FLAG_WRITE_STALL) { 608 usb2_transfer_start(sc->sc_xfer[UMCT_BULK_CS_WR]); 609 return; 610 } | 536tr_setup: |
611 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 612 sc->sc_obufsize, &actlen)) { 613 614 xfer->frlengths[0] = actlen; 615 usb2_start_hardware(xfer); 616 } 617 return; 618 619 default: /* Error */ 620 if (xfer->error != USB_ERR_CANCELLED) { | 537 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 538 sc->sc_obufsize, &actlen)) { 539 540 xfer->frlengths[0] = actlen; 541 usb2_start_hardware(xfer); 542 } 543 return; 544 545 default: /* Error */ 546 if (xfer->error != USB_ERR_CANCELLED) { |
621 sc->sc_flags |= UMCT_FLAG_WRITE_STALL; 622 usb2_transfer_start(sc->sc_xfer[UMCT_BULK_CS_WR]); | 547 /* try to clear stall first */ 548 xfer->flags.stall_pipe = 1; 549 goto tr_setup; |
623 } 624 return; | 550 } 551 return; |
625 | |
626 } 627} 628 629static void | 552 } 553} 554 555static void |
630umct_write_clear_stall_callback(struct usb2_xfer *xfer) 631{ 632 struct umct_softc *sc = xfer->priv_sc; 633 struct usb2_xfer *xfer_other = sc->sc_xfer[UMCT_BULK_DT_WR]; 634 635 if (usb2_clear_stall_callback(xfer, xfer_other)) { 636 DPRINTF("stall cleared\n"); 637 sc->sc_flags &= ~UMCT_FLAG_WRITE_STALL; 638 usb2_transfer_start(xfer_other); 639 } 640} 641 642static void | |
643umct_read_callback(struct usb2_xfer *xfer) 644{ 645 struct umct_softc *sc = xfer->priv_sc; 646 647 switch (USB_GET_STATE(xfer)) { 648 case USB_ST_TRANSFERRED: 649 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 650 0, xfer->actlen); 651 652 case USB_ST_SETUP: | 556umct_read_callback(struct usb2_xfer *xfer) 557{ 558 struct umct_softc *sc = xfer->priv_sc; 559 560 switch (USB_GET_STATE(xfer)) { 561 case USB_ST_TRANSFERRED: 562 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 563 0, xfer->actlen); 564 565 case USB_ST_SETUP: |
653 if (sc->sc_flags & UMCT_FLAG_READ_STALL) { 654 usb2_transfer_start(sc->sc_xfer[UMCT_BULK_CS_RD]); 655 } else { 656 xfer->frlengths[0] = xfer->max_data_length; 657 usb2_start_hardware(xfer); 658 } | 566tr_setup: 567 xfer->frlengths[0] = xfer->max_data_length; 568 usb2_start_hardware(xfer); |
659 return; 660 661 default: /* Error */ 662 if (xfer->error != USB_ERR_CANCELLED) { | 569 return; 570 571 default: /* Error */ 572 if (xfer->error != USB_ERR_CANCELLED) { |
663 sc->sc_flags |= UMCT_FLAG_READ_STALL; 664 usb2_transfer_start(sc->sc_xfer[UMCT_BULK_CS_RD]); | 573 /* try to clear stall first */ 574 xfer->flags.stall_pipe = 1; 575 goto tr_setup; |
665 } 666 return; | 576 } 577 return; |
667 | |
668 } 669} | 578 } 579} |
670 671static void 672umct_read_clear_stall_callback(struct usb2_xfer *xfer) 673{ 674 struct umct_softc *sc = xfer->priv_sc; 675 struct usb2_xfer *xfer_other = sc->sc_xfer[UMCT_BULK_DT_RD]; 676 677 if (usb2_clear_stall_callback(xfer, xfer_other)) { 678 DPRINTF("stall cleared\n"); 679 sc->sc_flags &= ~UMCT_FLAG_READ_STALL; 680 usb2_transfer_start(xfer_other); 681 } 682} | |