^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Parallel port device probing code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Philip Blundell <philb@gnu.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/parport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) const char *token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) const char *descr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) } classes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) { "", "Legacy device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) { "PRINTER", "Printer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) { "MODEM", "Modem" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) { "NET", "Network device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) { "HDC", "Hard disk" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) { "PCMCIA", "PCMCIA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) { "MEDIA", "Multimedia device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) { "FDC", "Floppy disk" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) { "PORTS", "Ports" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { "SCANNER", "Scanner" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) { "DIGICAM", "Digital camera" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) { "", "Unknown device" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) { "", "Unspecified" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) { "SCSIADAPTER", "SCSI adapter" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) { NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void pretty_print(struct parport *port, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct parport_device_info *info = &port->probe_info[device + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) pr_info("%s", port->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (device >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) pr_cont(" (addr %d)", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) pr_cont(": %s", classes[info->class].descr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (info->class)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) pr_cont(", %s %s", info->mfr, info->model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void parse_data(struct parport *port, int device, char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) char *p = txt, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int guessed_class = PARPORT_CLASS_UNSPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct parport_device_info *info = &port->probe_info[device + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!txt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) pr_warn("%s probe: memory squeeze\n", port->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) strcpy(txt, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) char *sep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) q = strchr(p, ';');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (q) *q = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) sep = strchr(p, ':');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (sep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) char *u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *(sep++) = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Get rid of trailing blanks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u = sep + strlen (sep) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) while (u >= p && *u == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *u-- = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) while (*u) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) *u = toupper(*u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) kfree(info->mfr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) info->mfr = kstrdup(sep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) kfree(info->model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) info->model = kstrdup(sep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) kfree(info->class_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) info->class_name = kstrdup(sep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) for (u = sep; *u; u++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) *u = toupper(*u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) for (i = 0; classes[i].token; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!strcmp(classes[i].token, sep)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) info->class = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) goto rock_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pr_warn("%s probe: warning, class '%s' not understood\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) port->name, sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) info->class = PARPORT_CLASS_OTHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) } else if (!strcmp(p, "CMD") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) !strcmp(p, "COMMAND SET")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) kfree(info->cmdset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) info->cmdset = kstrdup(sep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* if it speaks printer language, it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) probably a printer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (strstr(sep, "PJL") || strstr(sep, "PCL"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) guessed_class = PARPORT_CLASS_PRINTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kfree(info->description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) info->description = kstrdup(sep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) rock_on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) p = q + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* If the device didn't tell us its class, maybe we have managed to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) guess one from the things it did say. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (info->class == PARPORT_CLASS_UNSPEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) info->class = guessed_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pretty_print (port, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) kfree(txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Read up to count-1 bytes of device id. Terminate buffer with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * '\0'. Buffer begins with two Device ID length bytes as given by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static ssize_t parport_read_device_id (struct parport *port, char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned char length[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned lelen, belen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) size_t idlens[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned numidlens;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned current_idlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ssize_t retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* First two bytes are MSB,LSB of inclusive length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) retval = parport_read (port, length, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (retval != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (count < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) memcpy(buffer, length, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Some devices wrongly send LE length, and some send it two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * bytes short. Construct a sorted array of lengths to try. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) belen = (length[0] << 8) + length[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) lelen = (length[1] << 8) + length[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) idlens[0] = min(belen, lelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) idlens[1] = idlens[0]+2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (belen != lelen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int off = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* Don't try lengths of 0x100 and 0x200 as 1 and 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (idlens[0] <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) idlens[off] = max(belen, lelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) idlens[off+1] = idlens[off]+2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) numidlens = off+2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* Some devices don't truly implement Device ID, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * just return constant nibble forever. This catches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * also those cases. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (idlens[0] == 0 || idlens[0] > 0xFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) printk(KERN_DEBUG "%s: reported broken Device ID length of %#zX bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) port->name, idlens[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) numidlens = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Try to respect the given ID length despite all the bugs in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * the ID length. Read according to shortest possible ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) for (current_idlen = 0; current_idlen < numidlens; ++current_idlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) size_t idlen = idlens[current_idlen];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (idlen+1 >= count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) retval = parport_read (port, buffer+len, idlen-len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) len += retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (belen != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) printk(KERN_DEBUG "%s: Device ID was %zd bytes while device told it would be %d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) port->name, len, belen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* This might end reading the Device ID too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * soon. Hopefully the needed fields were already in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * the first 256 bytes or so that we must have read so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * far. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (buffer[len-1] == ';') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) printk(KERN_DEBUG "%s: Device ID reading stopped before device told data not available. Current idlen %u of %u, len bytes %02X %02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) port->name, current_idlen, numidlens,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) length[0], length[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (current_idlen < numidlens) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* Buffer not large enough, read to end of buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) size_t idlen, len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (len+1 < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) retval = parport_read (port, buffer+len, count-len-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) len += retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* Read the whole ID since some devices would not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * otherwise give back the Device ID from beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * next time when asked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) idlen = idlens[current_idlen];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) len2 = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) while(len2 < idlen && retval > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) char tmp[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) retval = parport_read (port, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) min(sizeof tmp, idlen-len2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) len2 += retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* In addition, there are broken devices out there that don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) even finish off with a semi-colon. We do not need to care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) about those at this time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) buffer[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Get Std 1284 Device ID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ssize_t parport_device_id (int devnum, char *buffer, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ssize_t retval = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct pardevice *dev = parport_open(devnum, daisy_dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) parport_claim_or_block (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* Negotiate to compatibility mode, and then to device ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * mode. (This so that we start form beginning of device ID if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * already in device ID mode.) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) retval = parport_negotiate (dev->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) retval = parport_read_device_id (dev->port, buffer, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (retval > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) parse_data (dev->port, dev->daisy, buffer+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) parport_release (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) parport_close (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }