Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }