1#include <sys/cdefs.h>
| 1#include <sys/cdefs.h>
|
2__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/ulpt2.c 187176 2009-01-13 19:03:47Z thompsa $");
| 2__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/ulpt2.c 187259 2009-01-15 02:35:40Z thompsa $");
|
3 4/* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */ 5 6/*- 7 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Lennart Augustsson (lennart@augustsson.net) at 12 * Carlstedt Research & Technology. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the NetBSD 25 * Foundation, Inc. and its contributors. 26 * 4. Neither the name of The NetBSD Foundation nor the names of its 27 * contributors may be used to endorse or promote products derived 28 * from this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 * POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43/* 44 * Printer Class spec: http://www.usb.org/developers/data/devclass/usbprint109.PDF 45 * Printer Class spec: http://www.usb.org/developers/devclass_docs/usbprint11.pdf 46 */ 47 48#include <dev/usb2/include/usb2_devid.h> 49#include <dev/usb2/include/usb2_standard.h> 50#include <dev/usb2/include/usb2_mfunc.h> 51#include <dev/usb2/include/usb2_error.h> 52 53#define USB_DEBUG_VAR ulpt_debug 54 55#include <dev/usb2/core/usb2_core.h> 56#include <dev/usb2/core/usb2_debug.h> 57#include <dev/usb2/core/usb2_process.h> 58#include <dev/usb2/core/usb2_request.h> 59#include <dev/usb2/core/usb2_lookup.h> 60#include <dev/usb2/core/usb2_util.h> 61#include <dev/usb2/core/usb2_busdma.h> 62#include <dev/usb2/core/usb2_mbuf.h> 63#include <dev/usb2/core/usb2_dev.h> 64#include <dev/usb2/core/usb2_parse.h> 65 66#include <sys/syslog.h> 67 68#if USB_DEBUG 69static int ulpt_debug = 0; 70 71SYSCTL_NODE(_hw_usb2, OID_AUTO, ulpt, CTLFLAG_RW, 0, "USB ulpt"); 72SYSCTL_INT(_hw_usb2_ulpt, OID_AUTO, debug, CTLFLAG_RW, 73 &ulpt_debug, 0, "Debug level"); 74#endif 75 76#define ULPT_BSIZE (1<<15) /* bytes */ 77#define ULPT_IFQ_MAXLEN 2 /* units */
| 3 4/* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */ 5 6/*- 7 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Lennart Augustsson (lennart@augustsson.net) at 12 * Carlstedt Research & Technology. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the NetBSD 25 * Foundation, Inc. and its contributors. 26 * 4. Neither the name of The NetBSD Foundation nor the names of its 27 * contributors may be used to endorse or promote products derived 28 * from this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 * POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43/* 44 * Printer Class spec: http://www.usb.org/developers/data/devclass/usbprint109.PDF 45 * Printer Class spec: http://www.usb.org/developers/devclass_docs/usbprint11.pdf 46 */ 47 48#include <dev/usb2/include/usb2_devid.h> 49#include <dev/usb2/include/usb2_standard.h> 50#include <dev/usb2/include/usb2_mfunc.h> 51#include <dev/usb2/include/usb2_error.h> 52 53#define USB_DEBUG_VAR ulpt_debug 54 55#include <dev/usb2/core/usb2_core.h> 56#include <dev/usb2/core/usb2_debug.h> 57#include <dev/usb2/core/usb2_process.h> 58#include <dev/usb2/core/usb2_request.h> 59#include <dev/usb2/core/usb2_lookup.h> 60#include <dev/usb2/core/usb2_util.h> 61#include <dev/usb2/core/usb2_busdma.h> 62#include <dev/usb2/core/usb2_mbuf.h> 63#include <dev/usb2/core/usb2_dev.h> 64#include <dev/usb2/core/usb2_parse.h> 65 66#include <sys/syslog.h> 67 68#if USB_DEBUG 69static int ulpt_debug = 0; 70 71SYSCTL_NODE(_hw_usb2, OID_AUTO, ulpt, CTLFLAG_RW, 0, "USB ulpt"); 72SYSCTL_INT(_hw_usb2_ulpt, OID_AUTO, debug, CTLFLAG_RW, 73 &ulpt_debug, 0, "Debug level"); 74#endif 75 76#define ULPT_BSIZE (1<<15) /* bytes */ 77#define ULPT_IFQ_MAXLEN 2 /* units */
|
78#define ULPT_N_TRANSFER 5 /* units */
| |
79 80#define UR_GET_DEVICE_ID 0x00 81#define UR_GET_PORT_STATUS 0x01 82#define UR_SOFT_RESET 0x02 83 84#define LPS_NERR 0x08 /* printer no error */ 85#define LPS_SELECT 0x10 /* printer selected */ 86#define LPS_NOPAPER 0x20 /* printer out of paper */ 87#define LPS_INVERT (LPS_SELECT|LPS_NERR) 88#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 89
| 78 79#define UR_GET_DEVICE_ID 0x00 80#define UR_GET_PORT_STATUS 0x01 81#define UR_SOFT_RESET 0x02 82 83#define LPS_NERR 0x08 /* printer no error */ 84#define LPS_SELECT 0x10 /* printer selected */ 85#define LPS_NOPAPER 0x20 /* printer out of paper */ 86#define LPS_INVERT (LPS_SELECT|LPS_NERR) 87#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 88
|
| 89enum { 90 ULPT_BULK_DT_WR, 91 ULPT_BULK_DT_RD, 92 ULPT_INTR_DT_RD, 93 ULPT_BULK_CS_WR, 94 ULPT_BULK_CS_RD, 95 ULPT_N_TRANSFER = 5, 96}; 97
|
90struct ulpt_softc { 91 struct usb2_fifo_sc sc_fifo; 92 struct usb2_fifo_sc sc_fifo_noreset; 93 struct mtx sc_mtx; 94 struct usb2_callout sc_watchdog; 95 96 device_t sc_dev; 97 struct usb2_device *sc_udev; 98 struct usb2_fifo *sc_fifo_open[2]; 99 struct usb2_xfer *sc_xfer[ULPT_N_TRANSFER]; 100 101 int sc_fflags; /* current open flags, FREAD and 102 * FWRITE */ 103 104 uint8_t sc_flags; 105#define ULPT_FLAG_READ_STALL 0x04 /* read transfer stalled */ 106#define ULPT_FLAG_WRITE_STALL 0x08 /* write transfer stalled */ 107 108 uint8_t sc_iface_no; 109 uint8_t sc_last_status; 110 uint8_t sc_zlps; /* number of consequtive zero length 111 * packets received */ 112}; 113 114/* prototypes */ 115 116static device_probe_t ulpt_probe; 117static device_attach_t ulpt_attach; 118static device_detach_t ulpt_detach; 119 120static usb2_callback_t ulpt_write_callback; 121static usb2_callback_t ulpt_write_clear_stall_callback; 122static usb2_callback_t ulpt_read_callback; 123static usb2_callback_t ulpt_read_clear_stall_callback; 124static usb2_callback_t ulpt_status_callback; 125 126static void ulpt_reset(struct ulpt_softc *); 127static void ulpt_watchdog(void *); 128 129static usb2_fifo_close_t ulpt_close; 130static usb2_fifo_cmd_t ulpt_start_read; 131static usb2_fifo_cmd_t ulpt_start_write; 132static usb2_fifo_cmd_t ulpt_stop_read; 133static usb2_fifo_cmd_t ulpt_stop_write; 134static usb2_fifo_ioctl_t ulpt_ioctl; 135static usb2_fifo_open_t ulpt_open; 136static usb2_fifo_open_t unlpt_open; 137 138static struct usb2_fifo_methods ulpt_fifo_methods = { 139 .f_close = &ulpt_close, 140 .f_ioctl = &ulpt_ioctl, 141 .f_open = &ulpt_open, 142 .f_start_read = &ulpt_start_read, 143 .f_start_write = &ulpt_start_write, 144 .f_stop_read = &ulpt_stop_read, 145 .f_stop_write = &ulpt_stop_write, 146 .basename[0] = "ulpt", 147}; 148 149static struct usb2_fifo_methods unlpt_fifo_methods = { 150 .f_close = &ulpt_close, 151 .f_ioctl = &ulpt_ioctl, 152 .f_open = &unlpt_open, 153 .f_start_read = &ulpt_start_read, 154 .f_start_write = &ulpt_start_write, 155 .f_stop_read = &ulpt_stop_read, 156 .f_stop_write = &ulpt_stop_write, 157 .basename[0] = "unlpt", 158}; 159 160static void 161ulpt_reset(struct ulpt_softc *sc) 162{ 163 struct usb2_device_request req; 164 165 DPRINTFN(2, "\n"); 166 167 req.bRequest = UR_SOFT_RESET; 168 USETW(req.wValue, 0); 169 USETW(req.wIndex, sc->sc_iface_no); 170 USETW(req.wLength, 0); 171 172 /* 173 * There was a mistake in the USB printer 1.0 spec that gave the 174 * request type as UT_WRITE_CLASS_OTHER; it should have been 175 * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, 176 * so we try both. 177 */ 178 179 mtx_lock(&sc->sc_mtx); 180 req.bmRequestType = UT_WRITE_CLASS_OTHER; 181 if (usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx, 182 &req, NULL, 0, NULL, 2 * USB_MS_HZ)) { /* 1.0 */ 183 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 184 if (usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx, 185 &req, NULL, 0, NULL, 2 * USB_MS_HZ)) { /* 1.1 */ 186 /* ignore error */ 187 } 188 } 189 mtx_unlock(&sc->sc_mtx); 190} 191 192static void 193ulpt_write_callback(struct usb2_xfer *xfer) 194{ 195 struct ulpt_softc *sc = xfer->priv_sc; 196 struct usb2_fifo *f = sc->sc_fifo_open[USB_FIFO_TX]; 197 uint32_t actlen; 198 199 if (f == NULL) { 200 /* should not happen */ 201 DPRINTF("no FIFO\n"); 202 return; 203 } 204 DPRINTF("state=0x%x\n", USB_GET_STATE(xfer)); 205 206 switch (USB_GET_STATE(xfer)) { 207 case USB_ST_TRANSFERRED: 208 case USB_ST_SETUP: 209 if (sc->sc_flags & ULPT_FLAG_WRITE_STALL) {
| 98struct ulpt_softc { 99 struct usb2_fifo_sc sc_fifo; 100 struct usb2_fifo_sc sc_fifo_noreset; 101 struct mtx sc_mtx; 102 struct usb2_callout sc_watchdog; 103 104 device_t sc_dev; 105 struct usb2_device *sc_udev; 106 struct usb2_fifo *sc_fifo_open[2]; 107 struct usb2_xfer *sc_xfer[ULPT_N_TRANSFER]; 108 109 int sc_fflags; /* current open flags, FREAD and 110 * FWRITE */ 111 112 uint8_t sc_flags; 113#define ULPT_FLAG_READ_STALL 0x04 /* read transfer stalled */ 114#define ULPT_FLAG_WRITE_STALL 0x08 /* write transfer stalled */ 115 116 uint8_t sc_iface_no; 117 uint8_t sc_last_status; 118 uint8_t sc_zlps; /* number of consequtive zero length 119 * packets received */ 120}; 121 122/* prototypes */ 123 124static device_probe_t ulpt_probe; 125static device_attach_t ulpt_attach; 126static device_detach_t ulpt_detach; 127 128static usb2_callback_t ulpt_write_callback; 129static usb2_callback_t ulpt_write_clear_stall_callback; 130static usb2_callback_t ulpt_read_callback; 131static usb2_callback_t ulpt_read_clear_stall_callback; 132static usb2_callback_t ulpt_status_callback; 133 134static void ulpt_reset(struct ulpt_softc *); 135static void ulpt_watchdog(void *); 136 137static usb2_fifo_close_t ulpt_close; 138static usb2_fifo_cmd_t ulpt_start_read; 139static usb2_fifo_cmd_t ulpt_start_write; 140static usb2_fifo_cmd_t ulpt_stop_read; 141static usb2_fifo_cmd_t ulpt_stop_write; 142static usb2_fifo_ioctl_t ulpt_ioctl; 143static usb2_fifo_open_t ulpt_open; 144static usb2_fifo_open_t unlpt_open; 145 146static struct usb2_fifo_methods ulpt_fifo_methods = { 147 .f_close = &ulpt_close, 148 .f_ioctl = &ulpt_ioctl, 149 .f_open = &ulpt_open, 150 .f_start_read = &ulpt_start_read, 151 .f_start_write = &ulpt_start_write, 152 .f_stop_read = &ulpt_stop_read, 153 .f_stop_write = &ulpt_stop_write, 154 .basename[0] = "ulpt", 155}; 156 157static struct usb2_fifo_methods unlpt_fifo_methods = { 158 .f_close = &ulpt_close, 159 .f_ioctl = &ulpt_ioctl, 160 .f_open = &unlpt_open, 161 .f_start_read = &ulpt_start_read, 162 .f_start_write = &ulpt_start_write, 163 .f_stop_read = &ulpt_stop_read, 164 .f_stop_write = &ulpt_stop_write, 165 .basename[0] = "unlpt", 166}; 167 168static void 169ulpt_reset(struct ulpt_softc *sc) 170{ 171 struct usb2_device_request req; 172 173 DPRINTFN(2, "\n"); 174 175 req.bRequest = UR_SOFT_RESET; 176 USETW(req.wValue, 0); 177 USETW(req.wIndex, sc->sc_iface_no); 178 USETW(req.wLength, 0); 179 180 /* 181 * There was a mistake in the USB printer 1.0 spec that gave the 182 * request type as UT_WRITE_CLASS_OTHER; it should have been 183 * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, 184 * so we try both. 185 */ 186 187 mtx_lock(&sc->sc_mtx); 188 req.bmRequestType = UT_WRITE_CLASS_OTHER; 189 if (usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx, 190 &req, NULL, 0, NULL, 2 * USB_MS_HZ)) { /* 1.0 */ 191 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 192 if (usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx, 193 &req, NULL, 0, NULL, 2 * USB_MS_HZ)) { /* 1.1 */ 194 /* ignore error */ 195 } 196 } 197 mtx_unlock(&sc->sc_mtx); 198} 199 200static void 201ulpt_write_callback(struct usb2_xfer *xfer) 202{ 203 struct ulpt_softc *sc = xfer->priv_sc; 204 struct usb2_fifo *f = sc->sc_fifo_open[USB_FIFO_TX]; 205 uint32_t actlen; 206 207 if (f == NULL) { 208 /* should not happen */ 209 DPRINTF("no FIFO\n"); 210 return; 211 } 212 DPRINTF("state=0x%x\n", USB_GET_STATE(xfer)); 213 214 switch (USB_GET_STATE(xfer)) { 215 case USB_ST_TRANSFERRED: 216 case USB_ST_SETUP: 217 if (sc->sc_flags & ULPT_FLAG_WRITE_STALL) {
|
210 usb2_transfer_start(sc->sc_xfer[3]);
| 218 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_CS_WR]);
|
211 break; 212 } 213 if (usb2_fifo_get_data(f, xfer->frbuffers, 214 0, xfer->max_data_length, &actlen, 0)) { 215 216 xfer->frlengths[0] = actlen; 217 usb2_start_hardware(xfer); 218 } 219 break; 220 221 default: /* Error */ 222 if (xfer->error != USB_ERR_CANCELLED) { 223 /* try to clear stall first */ 224 sc->sc_flags |= ULPT_FLAG_WRITE_STALL;
| 219 break; 220 } 221 if (usb2_fifo_get_data(f, xfer->frbuffers, 222 0, xfer->max_data_length, &actlen, 0)) { 223 224 xfer->frlengths[0] = actlen; 225 usb2_start_hardware(xfer); 226 } 227 break; 228 229 default: /* Error */ 230 if (xfer->error != USB_ERR_CANCELLED) { 231 /* try to clear stall first */ 232 sc->sc_flags |= ULPT_FLAG_WRITE_STALL;
|
225 usb2_transfer_start(sc->sc_xfer[3]);
| 233 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_CS_WR]);
|
226 } 227 break; 228 } 229} 230 231static void 232ulpt_write_clear_stall_callback(struct usb2_xfer *xfer) 233{ 234 struct ulpt_softc *sc = xfer->priv_sc;
| 234 } 235 break; 236 } 237} 238 239static void 240ulpt_write_clear_stall_callback(struct usb2_xfer *xfer) 241{ 242 struct ulpt_softc *sc = xfer->priv_sc;
|
235 struct usb2_xfer *xfer_other = sc->sc_xfer[0];
| 243 struct usb2_xfer *xfer_other = sc->sc_xfer[ULPT_BULK_DT_WR];
|
236 237 if (usb2_clear_stall_callback(xfer, xfer_other)) { 238 DPRINTF("stall cleared\n"); 239 sc->sc_flags &= ~ULPT_FLAG_WRITE_STALL; 240 usb2_transfer_start(xfer_other); 241 } 242} 243 244static void 245ulpt_read_callback(struct usb2_xfer *xfer) 246{ 247 struct ulpt_softc *sc = xfer->priv_sc; 248 struct usb2_fifo *f = sc->sc_fifo_open[USB_FIFO_RX]; 249 250 if (f == NULL) { 251 /* should not happen */ 252 DPRINTF("no FIFO\n"); 253 return; 254 } 255 DPRINTF("state=0x%x\n", USB_GET_STATE(xfer)); 256 257 switch (USB_GET_STATE(xfer)) { 258 case USB_ST_TRANSFERRED: 259 260 if (xfer->actlen == 0) { 261 262 if (sc->sc_zlps == 4) { 263 /* enable BULK throttle */ 264 xfer->interval = 500; /* ms */ 265 } else { 266 sc->sc_zlps++; 267 } 268 } else { 269 /* disable BULK throttle */ 270 271 xfer->interval = 0; 272 sc->sc_zlps = 0; 273 } 274 275 usb2_fifo_put_data(f, xfer->frbuffers, 276 0, xfer->actlen, 1); 277 278 case USB_ST_SETUP: 279 if (sc->sc_flags & ULPT_FLAG_READ_STALL) {
| 244 245 if (usb2_clear_stall_callback(xfer, xfer_other)) { 246 DPRINTF("stall cleared\n"); 247 sc->sc_flags &= ~ULPT_FLAG_WRITE_STALL; 248 usb2_transfer_start(xfer_other); 249 } 250} 251 252static void 253ulpt_read_callback(struct usb2_xfer *xfer) 254{ 255 struct ulpt_softc *sc = xfer->priv_sc; 256 struct usb2_fifo *f = sc->sc_fifo_open[USB_FIFO_RX]; 257 258 if (f == NULL) { 259 /* should not happen */ 260 DPRINTF("no FIFO\n"); 261 return; 262 } 263 DPRINTF("state=0x%x\n", USB_GET_STATE(xfer)); 264 265 switch (USB_GET_STATE(xfer)) { 266 case USB_ST_TRANSFERRED: 267 268 if (xfer->actlen == 0) { 269 270 if (sc->sc_zlps == 4) { 271 /* enable BULK throttle */ 272 xfer->interval = 500; /* ms */ 273 } else { 274 sc->sc_zlps++; 275 } 276 } else { 277 /* disable BULK throttle */ 278 279 xfer->interval = 0; 280 sc->sc_zlps = 0; 281 } 282 283 usb2_fifo_put_data(f, xfer->frbuffers, 284 0, xfer->actlen, 1); 285 286 case USB_ST_SETUP: 287 if (sc->sc_flags & ULPT_FLAG_READ_STALL) {
|
280 usb2_transfer_start(sc->sc_xfer[4]);
| 288 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_CS_RD]);
|
281 break; 282 } 283 if (usb2_fifo_put_bytes_max(f) != 0) { 284 xfer->frlengths[0] = xfer->max_data_length; 285 usb2_start_hardware(xfer); 286 } 287 break; 288 289 default: /* Error */ 290 /* disable BULK throttle */ 291 xfer->interval = 0; 292 sc->sc_zlps = 0; 293 294 if (xfer->error != USB_ERR_CANCELLED) { 295 /* try to clear stall first */ 296 sc->sc_flags |= ULPT_FLAG_READ_STALL;
| 289 break; 290 } 291 if (usb2_fifo_put_bytes_max(f) != 0) { 292 xfer->frlengths[0] = xfer->max_data_length; 293 usb2_start_hardware(xfer); 294 } 295 break; 296 297 default: /* Error */ 298 /* disable BULK throttle */ 299 xfer->interval = 0; 300 sc->sc_zlps = 0; 301 302 if (xfer->error != USB_ERR_CANCELLED) { 303 /* try to clear stall first */ 304 sc->sc_flags |= ULPT_FLAG_READ_STALL;
|
297 usb2_transfer_start(sc->sc_xfer[4]);
| 305 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_CS_RD]);
|
298 } 299 break; 300 } 301} 302 303static void 304ulpt_read_clear_stall_callback(struct usb2_xfer *xfer) 305{ 306 struct ulpt_softc *sc = xfer->priv_sc;
| 306 } 307 break; 308 } 309} 310 311static void 312ulpt_read_clear_stall_callback(struct usb2_xfer *xfer) 313{ 314 struct ulpt_softc *sc = xfer->priv_sc;
|
307 struct usb2_xfer *xfer_other = sc->sc_xfer[1];
| 315 struct usb2_xfer *xfer_other = sc->sc_xfer[ULPT_BULK_DT_RD];
|
308 309 if (usb2_clear_stall_callback(xfer, xfer_other)) { 310 DPRINTF("stall cleared\n"); 311 sc->sc_flags &= ~ULPT_FLAG_READ_STALL; 312 usb2_transfer_start(xfer_other); 313 } 314} 315 316static void 317ulpt_status_callback(struct usb2_xfer *xfer) 318{ 319 struct ulpt_softc *sc = xfer->priv_sc; 320 struct usb2_device_request req; 321 uint8_t cur_status; 322 uint8_t new_status; 323 324 switch (USB_GET_STATE(xfer)) { 325 case USB_ST_TRANSFERRED: 326 327 usb2_copy_out(xfer->frbuffers + 1, 0, &cur_status, 1); 328 329 cur_status = (cur_status ^ LPS_INVERT) & LPS_MASK; 330 new_status = cur_status & ~sc->sc_last_status; 331 sc->sc_last_status = cur_status; 332 333 if (new_status & LPS_SELECT) 334 log(LOG_NOTICE, "%s: offline\n", 335 device_get_nameunit(sc->sc_dev)); 336 else if (new_status & LPS_NOPAPER) 337 log(LOG_NOTICE, "%s: out of paper\n", 338 device_get_nameunit(sc->sc_dev)); 339 else if (new_status & LPS_NERR) 340 log(LOG_NOTICE, "%s: output error\n", 341 device_get_nameunit(sc->sc_dev)); 342 break; 343 344 case USB_ST_SETUP: 345 req.bmRequestType = UT_READ_CLASS_INTERFACE; 346 req.bRequest = UR_GET_PORT_STATUS; 347 USETW(req.wValue, 0); 348 req.wIndex[0] = sc->sc_iface_no; 349 req.wIndex[1] = 0; 350 USETW(req.wLength, 1); 351 352 usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req)); 353 354 xfer->frlengths[0] = sizeof(req); 355 xfer->frlengths[1] = 1; 356 xfer->nframes = 2; 357 usb2_start_hardware(xfer); 358 break; 359 360 default: /* Error */ 361 DPRINTF("error=%s\n", usb2_errstr(xfer->error)); 362 if (xfer->error != USB_ERR_CANCELLED) { 363 /* wait for next watchdog timeout */ 364 } 365 break; 366 } 367} 368 369static const struct usb2_config ulpt_config[ULPT_N_TRANSFER] = {
| 316 317 if (usb2_clear_stall_callback(xfer, xfer_other)) { 318 DPRINTF("stall cleared\n"); 319 sc->sc_flags &= ~ULPT_FLAG_READ_STALL; 320 usb2_transfer_start(xfer_other); 321 } 322} 323 324static void 325ulpt_status_callback(struct usb2_xfer *xfer) 326{ 327 struct ulpt_softc *sc = xfer->priv_sc; 328 struct usb2_device_request req; 329 uint8_t cur_status; 330 uint8_t new_status; 331 332 switch (USB_GET_STATE(xfer)) { 333 case USB_ST_TRANSFERRED: 334 335 usb2_copy_out(xfer->frbuffers + 1, 0, &cur_status, 1); 336 337 cur_status = (cur_status ^ LPS_INVERT) & LPS_MASK; 338 new_status = cur_status & ~sc->sc_last_status; 339 sc->sc_last_status = cur_status; 340 341 if (new_status & LPS_SELECT) 342 log(LOG_NOTICE, "%s: offline\n", 343 device_get_nameunit(sc->sc_dev)); 344 else if (new_status & LPS_NOPAPER) 345 log(LOG_NOTICE, "%s: out of paper\n", 346 device_get_nameunit(sc->sc_dev)); 347 else if (new_status & LPS_NERR) 348 log(LOG_NOTICE, "%s: output error\n", 349 device_get_nameunit(sc->sc_dev)); 350 break; 351 352 case USB_ST_SETUP: 353 req.bmRequestType = UT_READ_CLASS_INTERFACE; 354 req.bRequest = UR_GET_PORT_STATUS; 355 USETW(req.wValue, 0); 356 req.wIndex[0] = sc->sc_iface_no; 357 req.wIndex[1] = 0; 358 USETW(req.wLength, 1); 359 360 usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req)); 361 362 xfer->frlengths[0] = sizeof(req); 363 xfer->frlengths[1] = 1; 364 xfer->nframes = 2; 365 usb2_start_hardware(xfer); 366 break; 367 368 default: /* Error */ 369 DPRINTF("error=%s\n", usb2_errstr(xfer->error)); 370 if (xfer->error != USB_ERR_CANCELLED) { 371 /* wait for next watchdog timeout */ 372 } 373 break; 374 } 375} 376 377static const struct usb2_config ulpt_config[ULPT_N_TRANSFER] = {
|
370 [0] = {
| 378 [ULPT_BULK_DT_WR] = {
|
371 .type = UE_BULK, 372 .endpoint = UE_ADDR_ANY, 373 .direction = UE_DIR_OUT, 374 .mh.bufsize = ULPT_BSIZE, 375 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1}, 376 .mh.callback = &ulpt_write_callback, 377 }, 378
| 379 .type = UE_BULK, 380 .endpoint = UE_ADDR_ANY, 381 .direction = UE_DIR_OUT, 382 .mh.bufsize = ULPT_BSIZE, 383 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1}, 384 .mh.callback = &ulpt_write_callback, 385 }, 386
|
379 [1] = {
| 387 [ULPT_BULK_DT_RD] = {
|
380 .type = UE_BULK, 381 .endpoint = UE_ADDR_ANY, 382 .direction = UE_DIR_IN, 383 .mh.bufsize = ULPT_BSIZE, 384 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1}, 385 .mh.callback = &ulpt_read_callback, 386 }, 387
| 388 .type = UE_BULK, 389 .endpoint = UE_ADDR_ANY, 390 .direction = UE_DIR_IN, 391 .mh.bufsize = ULPT_BSIZE, 392 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1}, 393 .mh.callback = &ulpt_read_callback, 394 }, 395
|
388 [2] = {
| 396 [ULPT_INTR_DT_RD] = {
|
389 .type = UE_CONTROL, 390 .endpoint = 0x00, /* Control pipe */ 391 .direction = UE_DIR_ANY, 392 .mh.bufsize = sizeof(struct usb2_device_request) + 1, 393 .mh.callback = &ulpt_status_callback, 394 .mh.timeout = 1000, /* 1 second */ 395 }, 396
| 397 .type = UE_CONTROL, 398 .endpoint = 0x00, /* Control pipe */ 399 .direction = UE_DIR_ANY, 400 .mh.bufsize = sizeof(struct usb2_device_request) + 1, 401 .mh.callback = &ulpt_status_callback, 402 .mh.timeout = 1000, /* 1 second */ 403 }, 404
|
397 [3] = {
| 405 [ULPT_BULK_CS_WR] = {
|
398 .type = UE_CONTROL, 399 .endpoint = 0x00, /* Control pipe */ 400 .direction = UE_DIR_ANY, 401 .mh.bufsize = sizeof(struct usb2_device_request), 402 .mh.callback = &ulpt_write_clear_stall_callback, 403 .mh.timeout = 1000, /* 1 second */ 404 .mh.interval = 50, /* 50ms */ 405 }, 406
| 406 .type = UE_CONTROL, 407 .endpoint = 0x00, /* Control pipe */ 408 .direction = UE_DIR_ANY, 409 .mh.bufsize = sizeof(struct usb2_device_request), 410 .mh.callback = &ulpt_write_clear_stall_callback, 411 .mh.timeout = 1000, /* 1 second */ 412 .mh.interval = 50, /* 50ms */ 413 }, 414
|
407 [4] = {
| 415 [ULPT_BULK_CS_RD] = {
|
408 .type = UE_CONTROL, 409 .endpoint = 0x00, /* Control pipe */ 410 .direction = UE_DIR_ANY, 411 .mh.bufsize = sizeof(struct usb2_device_request), 412 .mh.callback = &ulpt_read_clear_stall_callback, 413 .mh.timeout = 1000, /* 1 second */ 414 .mh.interval = 50, /* 50ms */ 415 }, 416}; 417 418static void 419ulpt_start_read(struct usb2_fifo *fifo) 420{ 421 struct ulpt_softc *sc = fifo->priv_sc0; 422
| 416 .type = UE_CONTROL, 417 .endpoint = 0x00, /* Control pipe */ 418 .direction = UE_DIR_ANY, 419 .mh.bufsize = sizeof(struct usb2_device_request), 420 .mh.callback = &ulpt_read_clear_stall_callback, 421 .mh.timeout = 1000, /* 1 second */ 422 .mh.interval = 50, /* 50ms */ 423 }, 424}; 425 426static void 427ulpt_start_read(struct usb2_fifo *fifo) 428{ 429 struct ulpt_softc *sc = fifo->priv_sc0; 430
|
423 usb2_transfer_start(sc->sc_xfer[1]);
| 431 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_DT_RD]);
|
424} 425 426static void 427ulpt_stop_read(struct usb2_fifo *fifo) 428{ 429 struct ulpt_softc *sc = fifo->priv_sc0; 430
| 432} 433 434static void 435ulpt_stop_read(struct usb2_fifo *fifo) 436{ 437 struct ulpt_softc *sc = fifo->priv_sc0; 438
|
431 usb2_transfer_stop(sc->sc_xfer[4]); 432 usb2_transfer_stop(sc->sc_xfer[1]);
| 439 usb2_transfer_stop(sc->sc_xfer[ULPT_BULK_CS_RD]); 440 usb2_transfer_stop(sc->sc_xfer[ULPT_BULK_DT_RD]);
|
433} 434 435static void 436ulpt_start_write(struct usb2_fifo *fifo) 437{ 438 struct ulpt_softc *sc = fifo->priv_sc0; 439
| 441} 442 443static void 444ulpt_start_write(struct usb2_fifo *fifo) 445{ 446 struct ulpt_softc *sc = fifo->priv_sc0; 447
|
440 usb2_transfer_start(sc->sc_xfer[0]);
| 448 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_DT_WR]);
|
441} 442 443static void 444ulpt_stop_write(struct usb2_fifo *fifo) 445{ 446 struct ulpt_softc *sc = fifo->priv_sc0; 447
| 449} 450 451static void 452ulpt_stop_write(struct usb2_fifo *fifo) 453{ 454 struct ulpt_softc *sc = fifo->priv_sc0; 455
|
448 usb2_transfer_stop(sc->sc_xfer[3]); 449 usb2_transfer_stop(sc->sc_xfer[0]);
| 456 usb2_transfer_stop(sc->sc_xfer[ULPT_BULK_CS_WR]); 457 usb2_transfer_stop(sc->sc_xfer[ULPT_BULK_DT_WR]);
|
450} 451 452static int 453ulpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 454{ 455 struct ulpt_softc *sc = fifo->priv_sc0; 456 457 /* we assume that open is a serial process */ 458 459 if (sc->sc_fflags == 0) { 460 ulpt_reset(sc); 461 } 462 return (unlpt_open(fifo, fflags, td)); 463} 464 465static int 466unlpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 467{ 468 struct ulpt_softc *sc = fifo->priv_sc0; 469 470 if (sc->sc_fflags & fflags) { 471 return (EBUSY); 472 } 473 if (fflags & FREAD) { 474 /* clear stall first */ 475 mtx_lock(&sc->sc_mtx); 476 sc->sc_flags |= ULPT_FLAG_READ_STALL; 477 mtx_unlock(&sc->sc_mtx); 478 if (usb2_fifo_alloc_buffer(fifo,
| 458} 459 460static int 461ulpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 462{ 463 struct ulpt_softc *sc = fifo->priv_sc0; 464 465 /* we assume that open is a serial process */ 466 467 if (sc->sc_fflags == 0) { 468 ulpt_reset(sc); 469 } 470 return (unlpt_open(fifo, fflags, td)); 471} 472 473static int 474unlpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 475{ 476 struct ulpt_softc *sc = fifo->priv_sc0; 477 478 if (sc->sc_fflags & fflags) { 479 return (EBUSY); 480 } 481 if (fflags & FREAD) { 482 /* clear stall first */ 483 mtx_lock(&sc->sc_mtx); 484 sc->sc_flags |= ULPT_FLAG_READ_STALL; 485 mtx_unlock(&sc->sc_mtx); 486 if (usb2_fifo_alloc_buffer(fifo,
|
479 sc->sc_xfer[1]->max_data_length,
| 487 sc->sc_xfer[ULPT_BULK_DT_RD]->max_data_length,
|
480 ULPT_IFQ_MAXLEN)) { 481 return (ENOMEM); 482 } 483 /* set which FIFO is opened */ 484 sc->sc_fifo_open[USB_FIFO_RX] = fifo; 485 } 486 if (fflags & FWRITE) { 487 /* clear stall first */ 488 mtx_lock(&sc->sc_mtx); 489 sc->sc_flags |= ULPT_FLAG_WRITE_STALL; 490 mtx_unlock(&sc->sc_mtx); 491 if (usb2_fifo_alloc_buffer(fifo,
| 488 ULPT_IFQ_MAXLEN)) { 489 return (ENOMEM); 490 } 491 /* set which FIFO is opened */ 492 sc->sc_fifo_open[USB_FIFO_RX] = fifo; 493 } 494 if (fflags & FWRITE) { 495 /* clear stall first */ 496 mtx_lock(&sc->sc_mtx); 497 sc->sc_flags |= ULPT_FLAG_WRITE_STALL; 498 mtx_unlock(&sc->sc_mtx); 499 if (usb2_fifo_alloc_buffer(fifo,
|
492 sc->sc_xfer[0]->max_data_length,
| 500 sc->sc_xfer[ULPT_BULK_DT_WR]->max_data_length,
|
493 ULPT_IFQ_MAXLEN)) { 494 return (ENOMEM); 495 } 496 /* set which FIFO is opened */ 497 sc->sc_fifo_open[USB_FIFO_TX] = fifo; 498 } 499 sc->sc_fflags |= fflags & (FREAD | FWRITE); 500 return (0); 501} 502 503static void 504ulpt_close(struct usb2_fifo *fifo, int fflags, struct thread *td) 505{ 506 struct ulpt_softc *sc = fifo->priv_sc0; 507 508 sc->sc_fflags &= ~(fflags & (FREAD | FWRITE)); 509 510 if (fflags & (FREAD | FWRITE)) { 511 usb2_fifo_free_buffer(fifo); 512 } 513} 514 515static int 516ulpt_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, 517 int fflags, struct thread *td) 518{ 519 return (ENODEV); 520} 521 522static int 523ulpt_probe(device_t dev) 524{ 525 struct usb2_attach_arg *uaa = device_get_ivars(dev); 526 527 DPRINTFN(11, "\n"); 528 529 if (uaa->usb2_mode != USB_MODE_HOST) { 530 return (ENXIO); 531 } 532 if ((uaa->info.bInterfaceClass == UICLASS_PRINTER) && 533 (uaa->info.bInterfaceSubClass == UISUBCLASS_PRINTER) && 534 ((uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_UNI) || 535 (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_BI) || 536 (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_1284))) { 537 return (0); 538 } 539 return (ENXIO); 540} 541 542static int 543ulpt_attach(device_t dev) 544{ 545 struct usb2_attach_arg *uaa = device_get_ivars(dev); 546 struct ulpt_softc *sc = device_get_softc(dev); 547 struct usb2_interface_descriptor *id; 548 int unit = device_get_unit(dev); 549 int error; 550 uint8_t iface_index = uaa->info.bIfaceIndex; 551 uint8_t alt_index; 552 553 DPRINTFN(11, "sc=%p\n", sc); 554 555 sc->sc_dev = dev; 556 sc->sc_udev = uaa->device; 557 558 device_set_usb2_desc(dev); 559 560 mtx_init(&sc->sc_mtx, "ulpt lock", NULL, MTX_DEF | MTX_RECURSE); 561 562 usb2_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0); 563 564 /* search through all the descriptors looking for bidir mode */ 565 566 id = usb2_get_interface_descriptor(uaa->iface); 567 alt_index = 0 - 1; 568 while (1) { 569 if (id == NULL) { 570 break; 571 } 572 if ((id->bDescriptorType == UDESC_INTERFACE) && 573 (id->bLength >= sizeof(*id))) { 574 if (id->bInterfaceNumber != uaa->info.bIfaceNum) { 575 break; 576 } else { 577 alt_index++; 578 if ((id->bInterfaceClass == UICLASS_PRINTER) && 579 (id->bInterfaceSubClass == UISUBCLASS_PRINTER) && 580 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI)) { 581 goto found; 582 } 583 } 584 } 585 id = (void *)usb2_desc_foreach( 586 usb2_get_config_descriptor(uaa->device), (void *)id); 587 } 588 goto detach; 589 590found: 591 592 DPRINTF("setting alternate " 593 "config number: %d\n", alt_index); 594 595 if (alt_index) { 596 597 error = usb2_set_alt_interface_index 598 (uaa->device, iface_index, alt_index); 599 600 if (error) { 601 DPRINTF("could not set alternate " 602 "config, error=%s\n", usb2_errstr(error)); 603 goto detach; 604 } 605 } 606 sc->sc_iface_no = id->bInterfaceNumber; 607 608 error = usb2_transfer_setup(uaa->device, &iface_index, 609 sc->sc_xfer, ulpt_config, ULPT_N_TRANSFER, 610 sc, &sc->sc_mtx); 611 if (error) { 612 DPRINTF("error=%s\n", usb2_errstr(error)); 613 goto detach; 614 } 615 device_printf(sc->sc_dev, "using bi-directional mode\n"); 616 617#if 0 618/* 619 * This code is disabled because for some mysterious reason it causes 620 * printing not to work. But only sometimes, and mostly with 621 * UHCI and less often with OHCI. *sigh* 622 */ 623 { 624 struct usb2_config_descriptor *cd = usb2_get_config_descriptor(dev); 625 struct usb2_device_request req; 626 int len, alen; 627 628 req.bmRequestType = UT_READ_CLASS_INTERFACE; 629 req.bRequest = UR_GET_DEVICE_ID; 630 USETW(req.wValue, cd->bConfigurationValue); 631 USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 632 USETW(req.wLength, sizeof devinfo - 1); 633 error = usb2_do_request_flags(dev, &req, devinfo, USB_SHORT_XFER_OK, 634 &alen, USB_DEFAULT_TIMEOUT); 635 if (error) { 636 device_printf(sc->sc_dev, "cannot get device id\n"); 637 } else if (alen <= 2) { 638 device_printf(sc->sc_dev, "empty device id, no " 639 "printer connected?\n"); 640 } else { 641 /* devinfo now contains an IEEE-1284 device ID */ 642 len = ((devinfo[0] & 0xff) << 8) | (devinfo[1] & 0xff); 643 if (len > sizeof devinfo - 3) 644 len = sizeof devinfo - 3; 645 devinfo[len] = 0; 646 printf("%s: device id <", device_get_nameunit(sc->sc_dev)); 647 ieee1284_print_id(devinfo + 2); 648 printf(">\n"); 649 } 650 } 651#endif 652 653 /* set interface permissions */ 654 usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, 655 UID_ROOT, GID_OPERATOR, 0644); 656 657 error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 658 &ulpt_fifo_methods, &sc->sc_fifo, 659 unit, 0 - 1, uaa->info.bIfaceIndex); 660 if (error) { 661 goto detach; 662 } 663 error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 664 &unlpt_fifo_methods, &sc->sc_fifo_noreset, 665 unit, 0 - 1, uaa->info.bIfaceIndex); 666 if (error) { 667 goto detach; 668 } 669 /* start reading of status */ 670 671 mtx_lock(&sc->sc_mtx); 672 ulpt_watchdog(sc); 673 mtx_unlock(&sc->sc_mtx); 674 return (0); 675 676detach: 677 ulpt_detach(dev); 678 return (ENOMEM); 679} 680 681static int 682ulpt_detach(device_t dev) 683{ 684 struct ulpt_softc *sc = device_get_softc(dev); 685 686 DPRINTF("sc=%p\n", sc); 687 688 usb2_fifo_detach(&sc->sc_fifo); 689 usb2_fifo_detach(&sc->sc_fifo_noreset); 690 691 mtx_lock(&sc->sc_mtx); 692 usb2_callout_stop(&sc->sc_watchdog); 693 mtx_unlock(&sc->sc_mtx); 694 695 usb2_transfer_unsetup(sc->sc_xfer, ULPT_N_TRANSFER); 696 697 usb2_callout_drain(&sc->sc_watchdog); 698 699 mtx_destroy(&sc->sc_mtx); 700 701 return (0); 702} 703 704#if 0 705/* XXX This does not belong here. */ 706 707/* 708 * Compare two strings until the second ends. 709 */ 710 711static uint8_t 712ieee1284_compare(const char *a, const char *b) 713{ 714 while (1) { 715 716 if (*b == 0) { 717 break; 718 } 719 if (*a != *b) { 720 return 1; 721 } 722 b++; 723 a++; 724 } 725 return 0; 726} 727 728/* 729 * Print select parts of an IEEE 1284 device ID. 730 */ 731void 732ieee1284_print_id(char *str) 733{ 734 char *p, *q; 735 736 for (p = str - 1; p; p = strchr(p, ';')) { 737 p++; /* skip ';' */ 738 if (ieee1284_compare(p, "MFG:") == 0 || 739 ieee1284_compare(p, "MANUFACTURER:") == 0 || 740 ieee1284_compare(p, "MDL:") == 0 || 741 ieee1284_compare(p, "MODEL:") == 0) { 742 q = strchr(p, ';'); 743 if (q) 744 printf("%.*s", (int)(q - p + 1), p); 745 } 746 } 747} 748 749#endif 750 751static void 752ulpt_watchdog(void *arg) 753{ 754 struct ulpt_softc *sc = arg; 755 756 mtx_assert(&sc->sc_mtx, MA_OWNED); 757
| 501 ULPT_IFQ_MAXLEN)) { 502 return (ENOMEM); 503 } 504 /* set which FIFO is opened */ 505 sc->sc_fifo_open[USB_FIFO_TX] = fifo; 506 } 507 sc->sc_fflags |= fflags & (FREAD | FWRITE); 508 return (0); 509} 510 511static void 512ulpt_close(struct usb2_fifo *fifo, int fflags, struct thread *td) 513{ 514 struct ulpt_softc *sc = fifo->priv_sc0; 515 516 sc->sc_fflags &= ~(fflags & (FREAD | FWRITE)); 517 518 if (fflags & (FREAD | FWRITE)) { 519 usb2_fifo_free_buffer(fifo); 520 } 521} 522 523static int 524ulpt_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, 525 int fflags, struct thread *td) 526{ 527 return (ENODEV); 528} 529 530static int 531ulpt_probe(device_t dev) 532{ 533 struct usb2_attach_arg *uaa = device_get_ivars(dev); 534 535 DPRINTFN(11, "\n"); 536 537 if (uaa->usb2_mode != USB_MODE_HOST) { 538 return (ENXIO); 539 } 540 if ((uaa->info.bInterfaceClass == UICLASS_PRINTER) && 541 (uaa->info.bInterfaceSubClass == UISUBCLASS_PRINTER) && 542 ((uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_UNI) || 543 (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_BI) || 544 (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_1284))) { 545 return (0); 546 } 547 return (ENXIO); 548} 549 550static int 551ulpt_attach(device_t dev) 552{ 553 struct usb2_attach_arg *uaa = device_get_ivars(dev); 554 struct ulpt_softc *sc = device_get_softc(dev); 555 struct usb2_interface_descriptor *id; 556 int unit = device_get_unit(dev); 557 int error; 558 uint8_t iface_index = uaa->info.bIfaceIndex; 559 uint8_t alt_index; 560 561 DPRINTFN(11, "sc=%p\n", sc); 562 563 sc->sc_dev = dev; 564 sc->sc_udev = uaa->device; 565 566 device_set_usb2_desc(dev); 567 568 mtx_init(&sc->sc_mtx, "ulpt lock", NULL, MTX_DEF | MTX_RECURSE); 569 570 usb2_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0); 571 572 /* search through all the descriptors looking for bidir mode */ 573 574 id = usb2_get_interface_descriptor(uaa->iface); 575 alt_index = 0 - 1; 576 while (1) { 577 if (id == NULL) { 578 break; 579 } 580 if ((id->bDescriptorType == UDESC_INTERFACE) && 581 (id->bLength >= sizeof(*id))) { 582 if (id->bInterfaceNumber != uaa->info.bIfaceNum) { 583 break; 584 } else { 585 alt_index++; 586 if ((id->bInterfaceClass == UICLASS_PRINTER) && 587 (id->bInterfaceSubClass == UISUBCLASS_PRINTER) && 588 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI)) { 589 goto found; 590 } 591 } 592 } 593 id = (void *)usb2_desc_foreach( 594 usb2_get_config_descriptor(uaa->device), (void *)id); 595 } 596 goto detach; 597 598found: 599 600 DPRINTF("setting alternate " 601 "config number: %d\n", alt_index); 602 603 if (alt_index) { 604 605 error = usb2_set_alt_interface_index 606 (uaa->device, iface_index, alt_index); 607 608 if (error) { 609 DPRINTF("could not set alternate " 610 "config, error=%s\n", usb2_errstr(error)); 611 goto detach; 612 } 613 } 614 sc->sc_iface_no = id->bInterfaceNumber; 615 616 error = usb2_transfer_setup(uaa->device, &iface_index, 617 sc->sc_xfer, ulpt_config, ULPT_N_TRANSFER, 618 sc, &sc->sc_mtx); 619 if (error) { 620 DPRINTF("error=%s\n", usb2_errstr(error)); 621 goto detach; 622 } 623 device_printf(sc->sc_dev, "using bi-directional mode\n"); 624 625#if 0 626/* 627 * This code is disabled because for some mysterious reason it causes 628 * printing not to work. But only sometimes, and mostly with 629 * UHCI and less often with OHCI. *sigh* 630 */ 631 { 632 struct usb2_config_descriptor *cd = usb2_get_config_descriptor(dev); 633 struct usb2_device_request req; 634 int len, alen; 635 636 req.bmRequestType = UT_READ_CLASS_INTERFACE; 637 req.bRequest = UR_GET_DEVICE_ID; 638 USETW(req.wValue, cd->bConfigurationValue); 639 USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 640 USETW(req.wLength, sizeof devinfo - 1); 641 error = usb2_do_request_flags(dev, &req, devinfo, USB_SHORT_XFER_OK, 642 &alen, USB_DEFAULT_TIMEOUT); 643 if (error) { 644 device_printf(sc->sc_dev, "cannot get device id\n"); 645 } else if (alen <= 2) { 646 device_printf(sc->sc_dev, "empty device id, no " 647 "printer connected?\n"); 648 } else { 649 /* devinfo now contains an IEEE-1284 device ID */ 650 len = ((devinfo[0] & 0xff) << 8) | (devinfo[1] & 0xff); 651 if (len > sizeof devinfo - 3) 652 len = sizeof devinfo - 3; 653 devinfo[len] = 0; 654 printf("%s: device id <", device_get_nameunit(sc->sc_dev)); 655 ieee1284_print_id(devinfo + 2); 656 printf(">\n"); 657 } 658 } 659#endif 660 661 /* set interface permissions */ 662 usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, 663 UID_ROOT, GID_OPERATOR, 0644); 664 665 error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 666 &ulpt_fifo_methods, &sc->sc_fifo, 667 unit, 0 - 1, uaa->info.bIfaceIndex); 668 if (error) { 669 goto detach; 670 } 671 error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 672 &unlpt_fifo_methods, &sc->sc_fifo_noreset, 673 unit, 0 - 1, uaa->info.bIfaceIndex); 674 if (error) { 675 goto detach; 676 } 677 /* start reading of status */ 678 679 mtx_lock(&sc->sc_mtx); 680 ulpt_watchdog(sc); 681 mtx_unlock(&sc->sc_mtx); 682 return (0); 683 684detach: 685 ulpt_detach(dev); 686 return (ENOMEM); 687} 688 689static int 690ulpt_detach(device_t dev) 691{ 692 struct ulpt_softc *sc = device_get_softc(dev); 693 694 DPRINTF("sc=%p\n", sc); 695 696 usb2_fifo_detach(&sc->sc_fifo); 697 usb2_fifo_detach(&sc->sc_fifo_noreset); 698 699 mtx_lock(&sc->sc_mtx); 700 usb2_callout_stop(&sc->sc_watchdog); 701 mtx_unlock(&sc->sc_mtx); 702 703 usb2_transfer_unsetup(sc->sc_xfer, ULPT_N_TRANSFER); 704 705 usb2_callout_drain(&sc->sc_watchdog); 706 707 mtx_destroy(&sc->sc_mtx); 708 709 return (0); 710} 711 712#if 0 713/* XXX This does not belong here. */ 714 715/* 716 * Compare two strings until the second ends. 717 */ 718 719static uint8_t 720ieee1284_compare(const char *a, const char *b) 721{ 722 while (1) { 723 724 if (*b == 0) { 725 break; 726 } 727 if (*a != *b) { 728 return 1; 729 } 730 b++; 731 a++; 732 } 733 return 0; 734} 735 736/* 737 * Print select parts of an IEEE 1284 device ID. 738 */ 739void 740ieee1284_print_id(char *str) 741{ 742 char *p, *q; 743 744 for (p = str - 1; p; p = strchr(p, ';')) { 745 p++; /* skip ';' */ 746 if (ieee1284_compare(p, "MFG:") == 0 || 747 ieee1284_compare(p, "MANUFACTURER:") == 0 || 748 ieee1284_compare(p, "MDL:") == 0 || 749 ieee1284_compare(p, "MODEL:") == 0) { 750 q = strchr(p, ';'); 751 if (q) 752 printf("%.*s", (int)(q - p + 1), p); 753 } 754 } 755} 756 757#endif 758 759static void 760ulpt_watchdog(void *arg) 761{ 762 struct ulpt_softc *sc = arg; 763 764 mtx_assert(&sc->sc_mtx, MA_OWNED); 765
|
758 usb2_transfer_start(sc->sc_xfer[2]);
| 766 usb2_transfer_start(sc->sc_xfer[ULPT_INTR_DT_RD]);
|
759 760 usb2_callout_reset(&sc->sc_watchdog, 761 hz, &ulpt_watchdog, sc); 762} 763 764static devclass_t ulpt_devclass; 765 766static device_method_t ulpt_methods[] = { 767 DEVMETHOD(device_probe, ulpt_probe), 768 DEVMETHOD(device_attach, ulpt_attach), 769 DEVMETHOD(device_detach, ulpt_detach), 770 {0, 0} 771}; 772 773static driver_t ulpt_driver = { 774 .name = "ulpt", 775 .methods = ulpt_methods, 776 .size = sizeof(struct ulpt_softc), 777}; 778 779DRIVER_MODULE(ulpt, ushub, ulpt_driver, ulpt_devclass, NULL, 0); 780MODULE_DEPEND(ulpt, usb2_core, 1, 1, 1); 781MODULE_DEPEND(ulpt, usb2_serial, 1, 1, 1);
| 767 768 usb2_callout_reset(&sc->sc_watchdog, 769 hz, &ulpt_watchdog, sc); 770} 771 772static devclass_t ulpt_devclass; 773 774static device_method_t ulpt_methods[] = { 775 DEVMETHOD(device_probe, ulpt_probe), 776 DEVMETHOD(device_attach, ulpt_attach), 777 DEVMETHOD(device_detach, ulpt_detach), 778 {0, 0} 779}; 780 781static driver_t ulpt_driver = { 782 .name = "ulpt", 783 .methods = ulpt_methods, 784 .size = sizeof(struct ulpt_softc), 785}; 786 787DRIVER_MODULE(ulpt, ushub, ulpt_driver, ulpt_devclass, NULL, 0); 788MODULE_DEPEND(ulpt, usb2_core, 1, 1, 1); 789MODULE_DEPEND(ulpt, usb2_serial, 1, 1, 1);
|