1 1.108 andvar /* $NetBSD: ulpt.c,v 1.108 2025/04/14 16:43:00 andvar Exp $ */ 2 1.1 augustss 3 1.1 augustss /* 4 1.60 augustss * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. 5 1.1 augustss * All rights reserved. 6 1.1 augustss * 7 1.3 augustss * This code is derived from software contributed to The NetBSD Foundation 8 1.37 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at 9 1.3 augustss * Carlstedt Research & Technology. 10 1.1 augustss * 11 1.1 augustss * Redistribution and use in source and binary forms, with or without 12 1.1 augustss * modification, are permitted provided that the following conditions 13 1.1 augustss * are met: 14 1.1 augustss * 1. Redistributions of source code must retain the above copyright 15 1.1 augustss * notice, this list of conditions and the following disclaimer. 16 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 augustss * notice, this list of conditions and the following disclaimer in the 18 1.1 augustss * documentation and/or other materials provided with the distribution. 19 1.1 augustss * 20 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 augustss * POSSIBILITY OF SUCH DAMAGE. 31 1.11 augustss */ 32 1.11 augustss 33 1.11 augustss /* 34 1.108 andvar * Printer Class spec: https://www.usb.org/sites/default/files/usbprint11a021811.pdf 35 1.1 augustss */ 36 1.44 lukem 37 1.44 lukem #include <sys/cdefs.h> 38 1.108 andvar __KERNEL_RCSID(0, "$NetBSD: ulpt.c,v 1.108 2025/04/14 16:43:00 andvar Exp $"); 39 1.98 skrll 40 1.98 skrll #ifdef _KERNEL_OPT 41 1.98 skrll #include "opt_usb.h" 42 1.98 skrll #endif 43 1.27 augustss 44 1.1 augustss #include <sys/param.h> 45 1.1 augustss #include <sys/systm.h> 46 1.1 augustss #include <sys/proc.h> 47 1.1 augustss #include <sys/kernel.h> 48 1.60 augustss #include <sys/fcntl.h> 49 1.8 augustss #include <sys/device.h> 50 1.1 augustss #include <sys/ioctl.h> 51 1.1 augustss #include <sys/uio.h> 52 1.1 augustss #include <sys/conf.h> 53 1.12 augustss #include <sys/vnode.h> 54 1.1 augustss #include <sys/syslog.h> 55 1.1 augustss 56 1.60 augustss #include <machine/vmparam.h> /* PAGE_SIZE */ 57 1.60 augustss 58 1.1 augustss #include <dev/usb/usb.h> 59 1.1 augustss #include <dev/usb/usbdi.h> 60 1.1 augustss #include <dev/usb/usbdi_util.h> 61 1.1 augustss #include <dev/usb/usbdevs.h> 62 1.1 augustss #include <dev/usb/usb_quirks.h> 63 1.1 augustss 64 1.103 mrg #include "ioconf.h" 65 1.103 mrg 66 1.1 augustss #define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ 67 1.1 augustss #define STEP hz/4 68 1.1 augustss 69 1.1 augustss #define LPTPRI (PZERO+8) 70 1.60 augustss #define ULPT_BSIZE PAGE_SIZE 71 1.60 augustss 72 1.60 augustss #define ULPT_READS_PER_SEC 5 73 1.96 skrll /* XXX Why is 10 us a reasonable value? */ 74 1.60 augustss #define ULPT_READ_TIMO 10 75 1.1 augustss 76 1.27 augustss #ifdef ULPT_DEBUG 77 1.85 dyoung #define DPRINTFN(n,x) if (ulptdebug>=(n)) printf x 78 1.1 augustss int ulptdebug = 0; 79 1.79 gdt /* 80 1.79 gdt * The strategy for debug levels is: 81 1.79 gdt * 1: attach-time operations 82 1.79 gdt * 2: open/close/status/reset 83 1.79 gdt * 3: read/write basic 84 1.79 gdt * 4: read/write details 85 1.79 gdt * 10: left over from previous debug code 86 1.79 gdt */ 87 1.1 augustss #else 88 1.1 augustss #define DPRINTFN(n,x) 89 1.1 augustss #endif 90 1.1 augustss 91 1.1 augustss #define UR_GET_DEVICE_ID 0 92 1.1 augustss #define UR_GET_PORT_STATUS 1 93 1.1 augustss #define UR_SOFT_RESET 2 94 1.1 augustss 95 1.1 augustss #define LPS_NERR 0x08 /* printer no error */ 96 1.1 augustss #define LPS_SELECT 0x10 /* printer selected */ 97 1.1 augustss #define LPS_NOPAPER 0x20 /* printer out of paper */ 98 1.1 augustss #define LPS_INVERT (LPS_SELECT|LPS_NERR) 99 1.1 augustss #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 100 1.1 augustss 101 1.1 augustss struct ulpt_softc { 102 1.85 dyoung device_t sc_dev; 103 1.96 skrll struct usbd_device *sc_udev; /* device */ 104 1.96 skrll struct usbd_interface *sc_iface; /* interface */ 105 1.1 augustss int sc_ifaceno; 106 1.42 augustss 107 1.42 augustss int sc_out; 108 1.96 skrll struct usbd_pipe *sc_out_pipe; /* bulk out pipe */ 109 1.96 skrll struct usbd_xfer *sc_out_xfer; 110 1.60 augustss void *sc_out_buf; 111 1.42 augustss 112 1.42 augustss int sc_in; 113 1.96 skrll struct usbd_pipe *sc_in_pipe; /* bulk in pipe */ 114 1.96 skrll struct usbd_xfer *sc_in_xfer; 115 1.60 augustss void *sc_in_buf; 116 1.60 augustss 117 1.85 dyoung struct callout sc_read_callout; /* to drain input on write-only opens */ 118 1.60 augustss int sc_has_callout; 119 1.1 augustss 120 1.1 augustss u_char sc_state; 121 1.1 augustss #define ULPT_OPEN 0x01 /* device is open */ 122 1.1 augustss #define ULPT_OBUSY 0x02 /* printer is busy doing output */ 123 1.1 augustss #define ULPT_INIT 0x04 /* waiting to initialize for open */ 124 1.1 augustss u_char sc_flags; 125 1.1 augustss #define ULPT_NOPRIME 0x40 /* don't prime on open */ 126 1.1 augustss u_char sc_laststatus; 127 1.12 augustss 128 1.12 augustss int sc_refcnt; 129 1.12 augustss u_char sc_dying; 130 1.1 augustss }; 131 1.1 augustss 132 1.104 maxv static dev_type_open(ulptopen); 133 1.104 maxv static dev_type_close(ulptclose); 134 1.104 maxv static dev_type_write(ulptwrite); 135 1.104 maxv static dev_type_read(ulptread); 136 1.104 maxv static dev_type_ioctl(ulptioctl); 137 1.52 gehenna 138 1.52 gehenna const struct cdevsw ulpt_cdevsw = { 139 1.94 dholland .d_open = ulptopen, 140 1.94 dholland .d_close = ulptclose, 141 1.94 dholland .d_read = ulptread, 142 1.94 dholland .d_write = ulptwrite, 143 1.94 dholland .d_ioctl = ulptioctl, 144 1.94 dholland .d_stop = nostop, 145 1.94 dholland .d_tty = notty, 146 1.94 dholland .d_poll = nopoll, 147 1.94 dholland .d_mmap = nommap, 148 1.94 dholland .d_kqfilter = nokqfilter, 149 1.95 dholland .d_discard = nodiscard, 150 1.94 dholland .d_flag = D_OTHER 151 1.52 gehenna }; 152 1.27 augustss 153 1.104 maxv static int ulpt_do_write(struct ulpt_softc *, struct uio *, int); 154 1.104 maxv static int ulpt_do_read(struct ulpt_softc *, struct uio *, int); 155 1.104 maxv static int ulpt_status(struct ulpt_softc *); 156 1.104 maxv static void ulpt_reset(struct ulpt_softc *); 157 1.104 maxv static int ulpt_statusmsg(u_char, struct ulpt_softc *); 158 1.104 maxv static void ulpt_read_cb(struct usbd_xfer *, void *, usbd_status); 159 1.104 maxv static void ulpt_tick(void *xsc); 160 1.1 augustss 161 1.42 augustss #if 0 162 1.38 augustss void ieee1284_print_id(char *); 163 1.42 augustss #endif 164 1.16 augustss 165 1.1 augustss #define ULPTUNIT(s) (minor(s) & 0x1f) 166 1.1 augustss #define ULPTFLAGS(s) (minor(s) & 0xe0) 167 1.1 augustss 168 1.27 augustss 169 1.104 maxv static int ulpt_match(device_t, cfdata_t, void *); 170 1.104 maxv static void ulpt_attach(device_t, device_t, void *); 171 1.104 maxv static int ulpt_detach(device_t, int); 172 1.104 maxv static int ulpt_activate(device_t, enum devact); 173 1.1 augustss 174 1.103 mrg 175 1.85 dyoung 176 1.85 dyoung CFATTACH_DECL_NEW(ulpt, sizeof(struct ulpt_softc), ulpt_match, ulpt_attach, 177 1.85 dyoung ulpt_detach, ulpt_activate); 178 1.85 dyoung 179 1.104 maxv static int 180 1.85 dyoung ulpt_match(device_t parent, cfdata_t match, void *aux) 181 1.1 augustss { 182 1.96 skrll struct usbif_attach_arg *uiaa = aux; 183 1.79 gdt /* XXX Print something useful, or don't. */ 184 1.1 augustss DPRINTFN(10,("ulpt_match\n")); 185 1.78 drochner 186 1.96 skrll if (uiaa->uiaa_class == UICLASS_PRINTER && 187 1.96 skrll uiaa->uiaa_subclass == UISUBCLASS_PRINTER && 188 1.96 skrll (uiaa->uiaa_proto == UIPROTO_PRINTER_UNI || 189 1.96 skrll uiaa->uiaa_proto == UIPROTO_PRINTER_BI || 190 1.96 skrll uiaa->uiaa_proto == UIPROTO_PRINTER_1284)) 191 1.96 skrll return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 192 1.96 skrll return UMATCH_NONE; 193 1.1 augustss } 194 1.1 augustss 195 1.104 maxv static void 196 1.85 dyoung ulpt_attach(device_t parent, device_t self, void *aux) 197 1.1 augustss { 198 1.85 dyoung struct ulpt_softc *sc = device_private(self); 199 1.96 skrll struct usbif_attach_arg *uiaa = aux; 200 1.96 skrll struct usbd_device *dev = uiaa->uiaa_device; 201 1.96 skrll struct usbd_interface *iface = uiaa->uiaa_iface; 202 1.42 augustss usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); 203 1.69 christos const usb_interface_descriptor_t *id; 204 1.42 augustss usbd_status err; 205 1.67 augustss char *devinfop; 206 1.1 augustss usb_endpoint_descriptor_t *ed; 207 1.96 skrll uint8_t epcount; 208 1.42 augustss int i, altno; 209 1.65 augustss usbd_desc_iter_t iter; 210 1.50 augustss 211 1.81 cube sc->sc_dev = self; 212 1.81 cube 213 1.83 plunky aprint_naive("\n"); 214 1.83 plunky aprint_normal("\n"); 215 1.83 plunky 216 1.67 augustss devinfop = usbd_devinfo_alloc(dev, 0); 217 1.81 cube aprint_normal_dev(self, "%s, iclass %d/%d\n", 218 1.67 augustss devinfop, ifcd->bInterfaceClass, ifcd->bInterfaceSubClass); 219 1.67 augustss usbd_devinfo_free(devinfop); 220 1.1 augustss 221 1.65 augustss /* Loop through descriptors looking for a bidir mode. */ 222 1.65 augustss usb_desc_iter_init(dev, &iter); 223 1.65 augustss for (altno = 0;;) { 224 1.69 christos id = (const usb_interface_descriptor_t *)usb_desc_iter_next(&iter); 225 1.65 augustss if (!id) 226 1.65 augustss break; 227 1.42 augustss if (id->bDescriptorType == UDESC_INTERFACE && 228 1.42 augustss id->bInterfaceNumber == ifcd->bInterfaceNumber) { 229 1.42 augustss if (id->bInterfaceClass == UICLASS_PRINTER && 230 1.42 augustss id->bInterfaceSubClass == UISUBCLASS_PRINTER && 231 1.56 augustss (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*|| 232 1.56 augustss id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/)) 233 1.42 augustss goto found; 234 1.42 augustss altno++; 235 1.66 perry } 236 1.42 augustss } 237 1.42 augustss id = ifcd; /* not found, use original */ 238 1.42 augustss found: 239 1.42 augustss if (id != ifcd) { 240 1.42 augustss /* Found a new bidir setting */ 241 1.79 gdt DPRINTFN(1, ("ulpt_attach: set altno = %d\n", altno)); 242 1.42 augustss err = usbd_set_interface(iface, altno); 243 1.42 augustss if (err) { 244 1.81 cube aprint_error_dev(self, 245 1.81 cube "setting alternate interface failed\n"); 246 1.42 augustss sc->sc_dying = 1; 247 1.85 dyoung return; 248 1.42 augustss } 249 1.1 augustss } 250 1.1 augustss 251 1.42 augustss epcount = 0; 252 1.42 augustss (void)usbd_endpoint_count(iface, &epcount); 253 1.42 augustss 254 1.42 augustss sc->sc_in = -1; 255 1.42 augustss sc->sc_out = -1; 256 1.42 augustss for (i = 0; i < epcount; i++) { 257 1.42 augustss ed = usbd_interface2endpoint_descriptor(iface, i); 258 1.42 augustss if (ed == NULL) { 259 1.81 cube aprint_error_dev(self, "couldn't get ep %d\n", i); 260 1.85 dyoung return; 261 1.42 augustss } 262 1.42 augustss if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 263 1.42 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 264 1.42 augustss sc->sc_in = ed->bEndpointAddress; 265 1.42 augustss } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 266 1.42 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 267 1.42 augustss sc->sc_out = ed->bEndpointAddress; 268 1.42 augustss } 269 1.42 augustss } 270 1.42 augustss if (sc->sc_out == -1) { 271 1.81 cube aprint_error_dev(self, "could not find bulk out endpoint\n"); 272 1.12 augustss sc->sc_dying = 1; 273 1.85 dyoung return; 274 1.12 augustss } 275 1.42 augustss 276 1.42 augustss if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { 277 1.42 augustss /* This device doesn't handle reading properly. */ 278 1.42 augustss sc->sc_in = -1; 279 1.42 augustss } 280 1.51 augustss 281 1.81 cube aprint_normal_dev(self, "using %s-directional mode\n", 282 1.51 augustss sc->sc_in >= 0 ? "bi" : "uni"); 283 1.42 augustss 284 1.42 augustss sc->sc_iface = iface; 285 1.1 augustss sc->sc_ifaceno = id->bInterfaceNumber; 286 1.42 augustss sc->sc_udev = dev; 287 1.1 augustss 288 1.22 augustss #if 0 289 1.22 augustss /* 290 1.36 augustss * This code is disabled because for some mysterious reason it causes 291 1.22 augustss * printing not to work. But only sometimes, and mostly with 292 1.22 augustss * UHCI and less often with OHCI. *sigh* 293 1.22 augustss */ 294 1.22 augustss { 295 1.22 augustss usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); 296 1.22 augustss usb_device_request_t req; 297 1.22 augustss int len, alen; 298 1.22 augustss 299 1.1 augustss req.bmRequestType = UT_READ_CLASS_INTERFACE; 300 1.1 augustss req.bRequest = UR_GET_DEVICE_ID; 301 1.1 augustss USETW(req.wValue, cd->bConfigurationValue); 302 1.1 augustss USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 303 1.68 soren USETW(req.wLength, DEVINFOSIZE - 1); 304 1.68 soren err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK, 305 1.48 augustss &alen, USBD_DEFAULT_TIMEOUT); 306 1.28 augustss if (err) { 307 1.85 dyoung printf("%s: cannot get device id\n", device_xname(sc->sc_dev)); 308 1.16 augustss } else if (alen <= 2) { 309 1.16 augustss printf("%s: empty device id, no printer connected?\n", 310 1.85 dyoung device_xname(sc->sc_dev)); 311 1.16 augustss } else { 312 1.68 soren /* devinfop now contains an IEEE-1284 device ID */ 313 1.68 soren len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff); 314 1.68 soren if (len > DEVINFOSIZE - 3) 315 1.68 soren len = DEVINFOSIZE - 3; 316 1.68 soren devinfop[len] = 0; 317 1.85 dyoung printf("%s: device id <", device_xname(sc->sc_dev)); 318 1.68 soren ieee1284_print_id(devinfop+2); 319 1.16 augustss printf(">\n"); 320 1.1 augustss } 321 1.22 augustss } 322 1.22 augustss #endif 323 1.1 augustss 324 1.97 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 325 1.31 augustss 326 1.79 gdt DPRINTFN(1, ("ulpt_attach: sc=%p in=%d out=%d\n", 327 1.79 gdt sc, sc->sc_out, sc->sc_in)); 328 1.79 gdt 329 1.85 dyoung return; 330 1.1 augustss } 331 1.1 augustss 332 1.104 maxv static int 333 1.85 dyoung ulpt_activate(device_t self, enum devact act) 334 1.12 augustss { 335 1.81 cube struct ulpt_softc *sc = device_private(self); 336 1.17 augustss 337 1.17 augustss switch (act) { 338 1.17 augustss case DVACT_DEACTIVATE: 339 1.17 augustss sc->sc_dying = 1; 340 1.84 dyoung return 0; 341 1.84 dyoung default: 342 1.84 dyoung return EOPNOTSUPP; 343 1.17 augustss } 344 1.12 augustss } 345 1.12 augustss 346 1.104 maxv static int 347 1.85 dyoung ulpt_detach(device_t self, int flags) 348 1.12 augustss { 349 1.85 dyoung struct ulpt_softc *sc = device_private(self); 350 1.27 augustss int s; 351 1.12 augustss int maj, mn; 352 1.12 augustss 353 1.79 gdt DPRINTFN(1, ("ulpt_detach: sc=%p\n", sc)); 354 1.12 augustss 355 1.12 augustss sc->sc_dying = 1; 356 1.42 augustss if (sc->sc_out_pipe != NULL) 357 1.42 augustss usbd_abort_pipe(sc->sc_out_pipe); 358 1.42 augustss if (sc->sc_in_pipe != NULL) 359 1.42 augustss usbd_abort_pipe(sc->sc_in_pipe); 360 1.12 augustss 361 1.12 augustss s = splusb(); 362 1.12 augustss if (--sc->sc_refcnt >= 0) { 363 1.108 andvar /* There is nothing to wake, aborting the pipe is enough */ 364 1.12 augustss /* Wait for processes to go away. */ 365 1.90 mrg usb_detach_waitold(sc->sc_dev); 366 1.12 augustss } 367 1.12 augustss splx(s); 368 1.12 augustss 369 1.12 augustss /* locate the major number */ 370 1.52 gehenna maj = cdevsw_lookup_major(&ulpt_cdevsw); 371 1.12 augustss 372 1.12 augustss /* Nuke the vnodes for any open instances (calls close). */ 373 1.72 thorpej mn = device_unit(self); 374 1.12 augustss vdevgone(maj, mn, mn, VCHR); 375 1.57 scw vdevgone(maj, mn | ULPT_NOPRIME , mn | ULPT_NOPRIME, VCHR); 376 1.31 augustss 377 1.107 maxv if (sc->sc_udev != NULL) 378 1.107 maxv usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 379 1.107 maxv sc->sc_dev); 380 1.12 augustss 381 1.96 skrll return 0; 382 1.12 augustss } 383 1.12 augustss 384 1.104 maxv static int 385 1.38 augustss ulpt_status(struct ulpt_softc *sc) 386 1.1 augustss { 387 1.1 augustss usb_device_request_t req; 388 1.28 augustss usbd_status err; 389 1.1 augustss u_char status; 390 1.1 augustss 391 1.1 augustss req.bmRequestType = UT_READ_CLASS_INTERFACE; 392 1.1 augustss req.bRequest = UR_GET_PORT_STATUS; 393 1.1 augustss USETW(req.wValue, 0); 394 1.1 augustss USETW(req.wIndex, sc->sc_ifaceno); 395 1.1 augustss USETW(req.wLength, 1); 396 1.28 augustss err = usbd_do_request(sc->sc_udev, &req, &status); 397 1.106 christos DPRINTFN(2, ("ulpt_status: status=0x%02x err=%d\n", status, err)); 398 1.28 augustss if (!err) 399 1.96 skrll return status; 400 1.1 augustss else 401 1.96 skrll return 0; 402 1.1 augustss } 403 1.1 augustss 404 1.104 maxv static void 405 1.38 augustss ulpt_reset(struct ulpt_softc *sc) 406 1.1 augustss { 407 1.1 augustss usb_device_request_t req; 408 1.1 augustss 409 1.79 gdt DPRINTFN(2, ("ulpt_reset\n")); 410 1.1 augustss req.bRequest = UR_SOFT_RESET; 411 1.1 augustss USETW(req.wValue, 0); 412 1.1 augustss USETW(req.wIndex, sc->sc_ifaceno); 413 1.1 augustss USETW(req.wLength, 0); 414 1.41 augustss 415 1.41 augustss /* 416 1.41 augustss * There was a mistake in the USB printer 1.0 spec that gave the 417 1.42 augustss * request type as UT_WRITE_CLASS_OTHER; it should have been 418 1.41 augustss * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, 419 1.41 augustss * so we try both. 420 1.41 augustss */ 421 1.49 augustss req.bmRequestType = UT_WRITE_CLASS_OTHER; 422 1.42 augustss if (usbd_do_request(sc->sc_udev, &req, 0)) { /* 1.0 */ 423 1.41 augustss req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 424 1.42 augustss (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */ 425 1.41 augustss } 426 1.1 augustss } 427 1.1 augustss 428 1.42 augustss int ulptusein = 1; 429 1.42 augustss 430 1.1 augustss /* 431 1.1 augustss * Reset the printer, then wait until it's selected and not busy. 432 1.1 augustss */ 433 1.104 maxv static int 434 1.76 christos ulptopen(dev_t dev, int flag, int mode, struct lwp *l) 435 1.1 augustss { 436 1.1 augustss u_char flags = ULPTFLAGS(dev); 437 1.26 augustss struct ulpt_softc *sc; 438 1.28 augustss usbd_status err; 439 1.1 augustss int spin, error; 440 1.26 augustss 441 1.85 dyoung sc = device_lookup_private(&ulpt_cd, ULPTUNIT(dev)); 442 1.85 dyoung if (sc == NULL) 443 1.85 dyoung return ENXIO; 444 1.1 augustss 445 1.30 augustss if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) 446 1.96 skrll return ENXIO; 447 1.1 augustss 448 1.1 augustss if (sc->sc_state) 449 1.96 skrll return EBUSY; 450 1.1 augustss 451 1.1 augustss sc->sc_state = ULPT_INIT; 452 1.1 augustss sc->sc_flags = flags; 453 1.105 christos DPRINTFN(2, ("ulptopen: flags=%#x\n", (unsigned)flags)); 454 1.1 augustss 455 1.39 augustss error = 0; 456 1.39 augustss sc->sc_refcnt++; 457 1.39 augustss 458 1.1 augustss if ((flags & ULPT_NOPRIME) == 0) 459 1.1 augustss ulpt_reset(sc); 460 1.1 augustss 461 1.1 augustss for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) { 462 1.79 gdt DPRINTFN(2, ("ulpt_open: waiting a while\n")); 463 1.1 augustss if (spin >= TIMEOUT) { 464 1.39 augustss error = EBUSY; 465 1.1 augustss sc->sc_state = 0; 466 1.39 augustss goto done; 467 1.1 augustss } 468 1.1 augustss 469 1.1 augustss /* wait 1/4 second, give up if we get a signal */ 470 1.102 skrll error = kpause("ulptop", true, STEP, NULL); 471 1.1 augustss if (error != EWOULDBLOCK) { 472 1.1 augustss sc->sc_state = 0; 473 1.39 augustss goto done; 474 1.39 augustss } 475 1.39 augustss 476 1.39 augustss if (sc->sc_dying) { 477 1.39 augustss error = ENXIO; 478 1.39 augustss sc->sc_state = 0; 479 1.39 augustss goto done; 480 1.1 augustss } 481 1.1 augustss } 482 1.1 augustss 483 1.42 augustss err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); 484 1.28 augustss if (err) { 485 1.39 augustss error = EIO; 486 1.60 augustss goto err0; 487 1.60 augustss } 488 1.96 skrll error = usbd_create_xfer(sc->sc_out_pipe, ULPT_BSIZE, 0, 0, 489 1.96 skrll &sc->sc_out_xfer); 490 1.96 skrll if (error) 491 1.60 augustss goto err2; 492 1.96 skrll sc->sc_out_buf = usbd_get_buffer(sc->sc_out_xfer); 493 1.60 augustss 494 1.42 augustss if (ulptusein && sc->sc_in != -1) { 495 1.79 gdt DPRINTFN(2, ("ulpt_open: opening input pipe %d\n", sc->sc_in)); 496 1.42 augustss err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe); 497 1.42 augustss if (err) { 498 1.42 augustss error = EIO; 499 1.60 augustss goto err2; 500 1.60 augustss } 501 1.96 skrll error = usbd_create_xfer(sc->sc_in_pipe, ULPT_BSIZE, 502 1.99 skrll 0, 0, &sc->sc_in_xfer); 503 1.96 skrll if (error) 504 1.60 augustss goto err3; 505 1.96 skrll sc->sc_in_buf = usbd_get_buffer(sc->sc_in_xfer); 506 1.68 soren /* If it's not opened for read then set up a reader. */ 507 1.70 rpaulo if (!(flag & FREAD)) { 508 1.79 gdt DPRINTFN(2, ("ulpt_open: start read callout\n")); 509 1.85 dyoung callout_init(&sc->sc_read_callout, 0); 510 1.85 dyoung callout_reset(&sc->sc_read_callout, hz/5, ulpt_tick, sc); 511 1.60 augustss sc->sc_has_callout = 1; 512 1.42 augustss } 513 1.42 augustss } 514 1.1 augustss 515 1.1 augustss sc->sc_state = ULPT_OPEN; 516 1.60 augustss goto done; 517 1.60 augustss 518 1.60 augustss err3: 519 1.60 augustss usbd_close_pipe(sc->sc_in_pipe); 520 1.60 augustss sc->sc_in_pipe = NULL; 521 1.60 augustss err2: 522 1.96 skrll usbd_destroy_xfer(sc->sc_out_xfer); 523 1.60 augustss sc->sc_out_xfer = NULL; 524 1.96 skrll 525 1.60 augustss usbd_close_pipe(sc->sc_out_pipe); 526 1.60 augustss sc->sc_out_pipe = NULL; 527 1.60 augustss err0: 528 1.60 augustss sc->sc_state = 0; 529 1.1 augustss 530 1.39 augustss done: 531 1.39 augustss if (--sc->sc_refcnt < 0) 532 1.90 mrg usb_detach_wakeupold(sc->sc_dev); 533 1.39 augustss 534 1.79 gdt DPRINTFN(2, ("ulptopen: done, error=%d\n", error)); 535 1.96 skrll return error; 536 1.1 augustss } 537 1.1 augustss 538 1.79 gdt /* 539 1.79 gdt * XXX Document return value semantics. 540 1.79 gdt */ 541 1.104 maxv static int 542 1.38 augustss ulpt_statusmsg(u_char status, struct ulpt_softc *sc) 543 1.1 augustss { 544 1.1 augustss u_char new; 545 1.1 augustss 546 1.1 augustss status = (status ^ LPS_INVERT) & LPS_MASK; 547 1.1 augustss new = status & ~sc->sc_laststatus; 548 1.1 augustss sc->sc_laststatus = status; 549 1.1 augustss 550 1.1 augustss if (new & LPS_SELECT) 551 1.85 dyoung log(LOG_NOTICE, "%s: offline\n", device_xname(sc->sc_dev)); 552 1.79 gdt if (new & LPS_NOPAPER) 553 1.85 dyoung log(LOG_NOTICE, "%s: out of paper\n", device_xname(sc->sc_dev)); 554 1.79 gdt if (new & LPS_NERR) 555 1.85 dyoung log(LOG_NOTICE, "%s: output error\n", device_xname(sc->sc_dev)); 556 1.1 augustss 557 1.96 skrll return status; 558 1.1 augustss } 559 1.1 augustss 560 1.104 maxv static int 561 1.76 christos ulptclose(dev_t dev, int flag, int mode, 562 1.76 christos struct lwp *l) 563 1.1 augustss { 564 1.26 augustss struct ulpt_softc *sc; 565 1.26 augustss 566 1.85 dyoung sc = device_lookup_private(&ulpt_cd, ULPTUNIT(dev)); 567 1.13 augustss 568 1.13 augustss if (sc->sc_state != ULPT_OPEN) 569 1.13 augustss /* We are being forced to close before the open completed. */ 570 1.96 skrll return 0; 571 1.1 augustss 572 1.60 augustss if (sc->sc_has_callout) { 573 1.79 gdt DPRINTFN(2, ("ulptclose: stopping read callout\n")); 574 1.92 martin callout_halt(&sc->sc_read_callout, NULL); 575 1.92 martin callout_destroy(&sc->sc_read_callout); 576 1.60 augustss sc->sc_has_callout = 0; 577 1.60 augustss } 578 1.60 augustss 579 1.42 augustss if (sc->sc_out_pipe != NULL) { 580 1.60 augustss usbd_abort_pipe(sc->sc_out_pipe); 581 1.42 augustss } 582 1.60 augustss if (sc->sc_out_xfer != NULL) { 583 1.96 skrll usbd_destroy_xfer(sc->sc_out_xfer); 584 1.60 augustss sc->sc_out_xfer = NULL; 585 1.60 augustss } 586 1.96 skrll if (sc->sc_out_pipe != NULL) { 587 1.96 skrll usbd_close_pipe(sc->sc_out_pipe); 588 1.96 skrll sc->sc_out_pipe = NULL; 589 1.96 skrll } 590 1.42 augustss if (sc->sc_in_pipe != NULL) { 591 1.42 augustss usbd_abort_pipe(sc->sc_in_pipe); 592 1.60 augustss } 593 1.60 augustss if (sc->sc_in_xfer != NULL) { 594 1.96 skrll usbd_destroy_xfer(sc->sc_in_xfer); 595 1.60 augustss sc->sc_in_xfer = NULL; 596 1.42 augustss } 597 1.96 skrll if (sc->sc_in_pipe != NULL) { 598 1.96 skrll usbd_close_pipe(sc->sc_in_pipe); 599 1.96 skrll sc->sc_in_pipe = NULL; 600 1.96 skrll } 601 1.1 augustss 602 1.1 augustss sc->sc_state = 0; 603 1.1 augustss 604 1.79 gdt DPRINTFN(2, ("ulptclose: closed\n")); 605 1.96 skrll return 0; 606 1.1 augustss } 607 1.1 augustss 608 1.104 maxv static int 609 1.76 christos ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) 610 1.1 augustss { 611 1.96 skrll uint32_t n; 612 1.1 augustss int error = 0; 613 1.23 augustss void *bufp; 614 1.96 skrll struct usbd_xfer *xfer; 615 1.28 augustss usbd_status err; 616 1.1 augustss 617 1.79 gdt DPRINTFN(3, ("ulptwrite\n")); 618 1.60 augustss xfer = sc->sc_out_xfer; 619 1.60 augustss bufp = sc->sc_out_buf; 620 1.100 riastrad while ((n = uimin(ULPT_BSIZE, uio->uio_resid)) != 0) { 621 1.1 augustss ulpt_statusmsg(ulpt_status(sc), sc); 622 1.23 augustss error = uiomove(bufp, n, uio); 623 1.6 augustss if (error) 624 1.6 augustss break; 625 1.79 gdt DPRINTFN(4, ("ulptwrite: transfer %d bytes\n", n)); 626 1.96 skrll err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, 0, 627 1.96 skrll USBD_NO_TIMEOUT, bufp, &n); 628 1.28 augustss if (err) { 629 1.79 gdt DPRINTFN(3, ("ulptwrite: error=%d\n", err)); 630 1.1 augustss error = EIO; 631 1.1 augustss break; 632 1.1 augustss } 633 1.1 augustss } 634 1.12 augustss 635 1.96 skrll return error; 636 1.12 augustss } 637 1.12 augustss 638 1.104 maxv static int 639 1.38 augustss ulptwrite(dev_t dev, struct uio *uio, int flags) 640 1.12 augustss { 641 1.26 augustss struct ulpt_softc *sc; 642 1.26 augustss int error; 643 1.26 augustss 644 1.85 dyoung sc = device_lookup_private(&ulpt_cd, ULPTUNIT(dev)); 645 1.21 augustss 646 1.21 augustss if (sc->sc_dying) 647 1.96 skrll return EIO; 648 1.12 augustss 649 1.12 augustss sc->sc_refcnt++; 650 1.12 augustss error = ulpt_do_write(sc, uio, flags); 651 1.12 augustss if (--sc->sc_refcnt < 0) 652 1.90 mrg usb_detach_wakeupold(sc->sc_dev); 653 1.96 skrll return error; 654 1.1 augustss } 655 1.1 augustss 656 1.79 gdt /* 657 1.79 gdt * Perform a read operation according to the given uio. 658 1.79 gdt * This should respect nonblocking I/O status. 659 1.96 skrll * 660 1.79 gdt * XXX Doing a short read when more data is available seems to be 661 1.79 gdt * problematic. See 662 1.79 gdt * http://www.freebsd.org/cgi/query-pr.cgi?pr=91538&cat= for a fix. 663 1.79 gdt * However, this will be unnecessary given a proper fix for the next 664 1.79 gdt * problem, and most actual callers read a lot. 665 1.79 gdt * 666 1.79 gdt * XXX This code should interact properly with select/poll, and that 667 1.79 gdt * requires the USB transactions to be queued and function before the 668 1.79 gdt * user does a read. Read will then consume data from a buffer, and 669 1.79 gdt * not interact with the device. See ucom.c for an example of how to 670 1.79 gdt * do this. 671 1.79 gdt */ 672 1.104 maxv static int 673 1.76 christos ulpt_do_read(struct ulpt_softc *sc, struct uio *uio, int flags) 674 1.60 augustss { 675 1.96 skrll uint32_t n, nread, nreq; 676 1.79 gdt int error = 0, nonblocking, timeout; 677 1.60 augustss void *bufp; 678 1.96 skrll struct usbd_xfer *xfer; 679 1.79 gdt usbd_status err = USBD_NORMAL_COMPLETION; 680 1.60 augustss 681 1.79 gdt /* XXX Resolve with background reader process. KASSERT? */ 682 1.79 gdt if (sc->sc_in_pipe == NULL) 683 1.79 gdt return EIO; 684 1.60 augustss 685 1.79 gdt if (flags & IO_NDELAY) 686 1.79 gdt nonblocking = 1; 687 1.79 gdt else 688 1.79 gdt nonblocking = 0; 689 1.79 gdt 690 1.79 gdt if (nonblocking) 691 1.79 gdt timeout = USBD_DEFAULT_TIMEOUT; /* 5 ms */ 692 1.79 gdt else 693 1.79 gdt timeout = USBD_NO_TIMEOUT; 694 1.79 gdt 695 1.82 bouyer DPRINTFN(3, ("ulptread nonblocking=%d uio_reside=%ld timeout=%d\n", 696 1.82 bouyer nonblocking, (u_long)uio->uio_resid, timeout)); 697 1.60 augustss 698 1.60 augustss xfer = sc->sc_in_xfer; 699 1.60 augustss bufp = sc->sc_in_buf; 700 1.79 gdt nread = 0; 701 1.100 riastrad while ((nreq = uimin(ULPT_BSIZE, uio->uio_resid)) != 0) { 702 1.79 gdt KASSERT(error == 0); 703 1.79 gdt if (error != 0) { 704 1.79 gdt printf("ulptread: pre-switch error %d != 0", error); 705 1.79 gdt goto done; 706 1.79 gdt } 707 1.79 gdt 708 1.79 gdt /* 709 1.101 skrll * XXX Even with the short timeout, this will sleep, 710 1.79 gdt * but it should be adequately prompt in practice. 711 1.79 gdt */ 712 1.79 gdt n = nreq; 713 1.79 gdt DPRINTFN(4, ("ulptread: transfer %d bytes, nonblocking=%d timeout=%d\n", 714 1.79 gdt n, nonblocking, timeout)); 715 1.60 augustss err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, 716 1.96 skrll USBD_SHORT_XFER_OK, timeout, bufp, &n); 717 1.79 gdt 718 1.79 gdt DPRINTFN(4, ("ulptread: transfer complete nreq %d n %d nread %d err %d\n", 719 1.79 gdt nreq, n, nread, err)); 720 1.79 gdt /* 721 1.79 gdt * Process "err" return, jumping to done if we set "error". 722 1.79 gdt */ 723 1.79 gdt switch (err) { 724 1.79 gdt case USBD_NORMAL_COMPLETION: 725 1.79 gdt if (n == 0) { 726 1.79 gdt DPRINTFN(3, ("ulptread: NORMAL n==0\n")); 727 1.79 gdt } 728 1.79 gdt break; 729 1.79 gdt 730 1.79 gdt case USBD_SHORT_XFER: 731 1.79 gdt /* We said SHORT_XFER_OK, so shouldn't happen. */ 732 1.79 gdt DPRINTFN(3, ("ulptread: SHORT n=%d\n", n)); 733 1.79 gdt break; 734 1.79 gdt 735 1.79 gdt case USBD_TIMEOUT: 736 1.79 gdt if (nonblocking == 0) { 737 1.79 gdt /* XXX Cannot happen; perhaps KASSERT. */ 738 1.79 gdt printf("ulptread: timeout in blocking mode\n"); 739 1.79 gdt error = EIO; 740 1.79 gdt goto done; 741 1.79 gdt } 742 1.79 gdt 743 1.79 gdt DPRINTFN(3, ("ulptread: TIMEOUT n %d nread %d error %d\n", 744 1.79 gdt n, nread, error)); 745 1.79 gdt /* 746 1.79 gdt * Don't set error until we understand why 747 1.79 gdt * this happens. 748 1.79 gdt */ 749 1.79 gdt break; 750 1.79 gdt 751 1.79 gdt case USBD_INTERRUPTED: 752 1.79 gdt /* 753 1.101 skrll * The sleep in usbd_bulk_transfer was 754 1.79 gdt * interrupted. Reflect it to the caller so 755 1.79 gdt * that reading can be interrupted. 756 1.79 gdt */ 757 1.79 gdt error = EINTR; 758 1.79 gdt DPRINTFN(3, ("ulptread: EINTR error %d\n", error)); 759 1.79 gdt goto done; 760 1.79 gdt break; 761 1.79 gdt 762 1.79 gdt default: 763 1.79 gdt /* Assume all other return codes are really errors. */ 764 1.60 augustss error = EIO; 765 1.79 gdt DPRINTFN(3, ("ulptread: n %d err %d error %d\n", 766 1.79 gdt n, err, error)); 767 1.79 gdt goto done; 768 1.60 augustss break; 769 1.60 augustss } 770 1.79 gdt /* XXX KASSERT */ 771 1.79 gdt if (error != 0) { 772 1.79 gdt printf("ulptread: post-switch error %d != 0", error); 773 1.79 gdt goto done; 774 1.79 gdt } 775 1.79 gdt 776 1.79 gdt if (n > 0) { 777 1.79 gdt /* 778 1.79 gdt * Record progress to enable later choosing 779 1.79 gdt * between short reads and EWOULDBLOCK. 780 1.79 gdt */ 781 1.79 gdt nread += n; 782 1.79 gdt 783 1.79 gdt /* Copy to userspace, giving up on any error. */ 784 1.79 gdt error = uiomove(bufp, n, uio); 785 1.79 gdt if (error != 0) 786 1.79 gdt break; 787 1.79 gdt } else { 788 1.79 gdt /* 789 1.79 gdt * We read 0 bytes, and therefore are done, 790 1.79 gdt * even if we aren't in nonblocking mode. 791 1.79 gdt */ 792 1.79 gdt if (error == 0 && nread == 0) 793 1.79 gdt error = EWOULDBLOCK; 794 1.79 gdt DPRINTFN(3, ("ulptread: read 0=>done error %d\n", 795 1.79 gdt error)); 796 1.79 gdt goto done; 797 1.79 gdt } 798 1.79 gdt 799 1.79 gdt /* 800 1.79 gdt * A short transfer indicates no more data will be 801 1.79 gdt * forthcoming. Terminate this read regardless of 802 1.79 gdt * whether we are in nonblocking mode. XXX Reconsider 803 1.79 gdt * for blocking mode; maybe we should continue to 804 1.108 andvar * block, but maybe it just doesn't make sense to do 805 1.79 gdt * blocking reads from devices like this. 806 1.79 gdt */ 807 1.79 gdt if (err == USBD_SHORT_XFER) { 808 1.79 gdt DPRINTFN(3, ("ulptread: SHORT=>done n %d nread %d err %d error %d\n", 809 1.79 gdt n, nread, err, error)); 810 1.60 augustss break; 811 1.79 gdt } 812 1.60 augustss } 813 1.60 augustss 814 1.79 gdt done: 815 1.79 gdt DPRINTFN(3, ("ulptread: finished n %d nread %d err %d error %d\n", 816 1.79 gdt n, nread, err, error)); 817 1.96 skrll return error; 818 1.60 augustss } 819 1.60 augustss 820 1.104 maxv static int 821 1.60 augustss ulptread(dev_t dev, struct uio *uio, int flags) 822 1.60 augustss { 823 1.60 augustss struct ulpt_softc *sc; 824 1.60 augustss int error; 825 1.60 augustss 826 1.85 dyoung sc = device_lookup_private(&ulpt_cd, ULPTUNIT(dev)); 827 1.60 augustss 828 1.60 augustss if (sc->sc_dying) 829 1.96 skrll return EIO; 830 1.60 augustss 831 1.60 augustss sc->sc_refcnt++; 832 1.60 augustss error = ulpt_do_read(sc, uio, flags); 833 1.60 augustss if (--sc->sc_refcnt < 0) 834 1.90 mrg usb_detach_wakeupold(sc->sc_dev); 835 1.96 skrll return error; 836 1.60 augustss } 837 1.60 augustss 838 1.104 maxv static void 839 1.96 skrll ulpt_read_cb(struct usbd_xfer *xfer, void *priv, 840 1.76 christos usbd_status status) 841 1.60 augustss { 842 1.60 augustss usbd_status err; 843 1.96 skrll uint32_t n; 844 1.96 skrll void *xsc; 845 1.60 augustss struct ulpt_softc *sc; 846 1.60 augustss 847 1.60 augustss usbd_get_xfer_status(xfer, &xsc, NULL, &n, &err); 848 1.60 augustss sc = xsc; 849 1.60 augustss 850 1.79 gdt DPRINTFN(4, ("ulpt_read_cb: start sc=%p, err=%d n=%d\n", sc, err, n)); 851 1.60 augustss 852 1.60 augustss #ifdef ULPT_DEBUG 853 1.60 augustss if (!err && n > 0) 854 1.79 gdt DPRINTFN(3, ("ulpt_tick: discarding %d bytes\n", n)); 855 1.60 augustss #endif 856 1.60 augustss if (!err || err == USBD_TIMEOUT) 857 1.85 dyoung callout_reset(&sc->sc_read_callout, hz / ULPT_READS_PER_SEC, 858 1.60 augustss ulpt_tick, sc); 859 1.60 augustss } 860 1.60 augustss 861 1.79 gdt /* 862 1.79 gdt * For devices which are not opened for reading, this function is 863 1.79 gdt * called continuously to start read bulk transfers to avoid the 864 1.79 gdt * printer overflowing its output buffer. 865 1.96 skrll * 866 1.79 gdt * XXX This should be adapted for continuous reads to allow select to 867 1.79 gdt * work; see do_ulpt_read(). 868 1.79 gdt */ 869 1.104 maxv static void 870 1.60 augustss ulpt_tick(void *xsc) 871 1.60 augustss { 872 1.60 augustss struct ulpt_softc *sc = xsc; 873 1.93 martin usbd_status err __unused; 874 1.60 augustss 875 1.60 augustss if (sc == NULL || sc->sc_dying) 876 1.60 augustss return; 877 1.60 augustss 878 1.96 skrll usbd_setup_xfer(sc->sc_in_xfer, sc, sc->sc_in_buf, ULPT_BSIZE, 879 1.96 skrll USBD_SHORT_XFER_OK, ULPT_READ_TIMO, ulpt_read_cb); 880 1.60 augustss err = usbd_transfer(sc->sc_in_xfer); 881 1.79 gdt DPRINTFN(3, ("ulpt_tick: sc=%p err=%d\n", sc, err)); 882 1.60 augustss } 883 1.60 augustss 884 1.104 maxv static int 885 1.77 christos ulptioctl(dev_t dev, u_long cmd, void *data, 886 1.76 christos int flag, struct lwp *l) 887 1.1 augustss { 888 1.93 martin #if 0 889 1.79 gdt struct ulpt_softc *sc; 890 1.79 gdt 891 1.85 dyoung sc = device_lookup_private(&ulpt_cd, ULPTUNIT(dev)); 892 1.93 martin #endif 893 1.79 gdt 894 1.79 gdt switch (cmd) { 895 1.79 gdt case FIONBIO: 896 1.79 gdt return 0; 897 1.79 gdt } 898 1.79 gdt 899 1.75 christos return ENODEV; 900 1.16 augustss } 901 1.16 augustss 902 1.22 augustss #if 0 903 1.16 augustss /* XXX This does not belong here. */ 904 1.16 augustss /* 905 1.17 augustss * Print select parts of a IEEE 1284 device ID. 906 1.16 augustss */ 907 1.16 augustss void 908 1.38 augustss ieee1284_print_id(char *str) 909 1.16 augustss { 910 1.16 augustss char *p, *q; 911 1.16 augustss 912 1.16 augustss for (p = str-1; p; p = strchr(p, ';')) { 913 1.16 augustss p++; /* skip ';' */ 914 1.16 augustss if (strncmp(p, "MFG:", 4) == 0 || 915 1.16 augustss strncmp(p, "MANUFACTURER:", 14) == 0 || 916 1.16 augustss strncmp(p, "MDL:", 4) == 0 || 917 1.16 augustss strncmp(p, "MODEL:", 6) == 0) { 918 1.16 augustss q = strchr(p, ';'); 919 1.16 augustss if (q) 920 1.16 augustss printf("%.*s", (int)(q - p + 1), p); 921 1.16 augustss } 922 1.16 augustss } 923 1.1 augustss } 924 1.22 augustss #endif 925