Deleted Added
full compact
ulpt.c (187176) ulpt.c (187259)
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);