1 /* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $ 2 * Parallel port device probing code 3 * 4 * Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de 5 * Philip Blundell <philb@gnu.org> 6 */ 7 8 #include <linux/module.h> 9 #include <linux/parport.h> 10 #include <linux/ctype.h> 11 #include <linux/string.h> 12 #include <asm/uaccess.h> 13 14 static struct { 15 char *token; 16 char *descr; 17 } classes[] = { 18 { "", "Legacy device" }, 19 { "PRINTER", "Printer" }, 20 { "MODEM", "Modem" }, 21 { "NET", "Network device" }, 22 { "HDC", "Hard disk" }, 23 { "PCMCIA", "PCMCIA" }, 24 { "MEDIA", "Multimedia device" }, 25 { "FDC", "Floppy disk" }, 26 { "PORTS", "Ports" }, 27 { "SCANNER", "Scanner" }, 28 { "DIGICAM", "Digital camera" }, 29 { "", "Unknown device" }, 30 { "", "Unspecified" }, 31 { "SCSIADAPTER", "SCSI adapter" }, 32 { NULL, NULL } 33 }; 34 35 static void pretty_print(struct parport *port, int device) 36 { 37 struct parport_device_info *info = &port->probe_info[device + 1]; 38 39 printk(KERN_INFO "%s", port->name); 40 41 if (device >= 0) 42 printk (" (addr %d)", device); 43 44 printk (": %s", classes[info->class].descr); 45 if (info->class) 46 printk(", %s %s", info->mfr, info->model); 47 48 printk("\n"); 49 } 50 51 static void parse_data(struct parport *port, int device, char *str) 52 { 53 char *txt = kmalloc(strlen(str)+1, GFP_KERNEL); 54 char *p = txt, *q; 55 int guessed_class = PARPORT_CLASS_UNSPEC; 56 struct parport_device_info *info = &port->probe_info[device + 1]; 57 58 if (!txt) { 59 printk(KERN_WARNING "%s probe: memory squeeze\n", port->name); 60 return; 61 } 62 strcpy(txt, str); 63 while (p) { 64 char *sep; 65 q = strchr(p, ';'); 66 if (q) *q = 0; 67 sep = strchr(p, ':'); 68 if (sep) { 69 char *u; 70 *(sep++) = 0; 71 /* Get rid of trailing blanks */ 72 u = sep + strlen (sep) - 1; 73 while (u >= p && *u == ' ') 74 *u-- = '\0'; 75 u = p; 76 while (*u) { 77 *u = toupper(*u); 78 u++; 79 } 80 if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { 81 kfree(info->mfr); 82 info->mfr = kstrdup(sep, GFP_KERNEL); 83 } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) { 84 kfree(info->model); 85 info->model = kstrdup(sep, GFP_KERNEL); 86 } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) { 87 int i; 88 89 kfree(info->class_name); 90 info->class_name = kstrdup(sep, GFP_KERNEL); 91 for (u = sep; *u; u++) 92 *u = toupper(*u); 93 for (i = 0; classes[i].token; i++) { 94 if (!strcmp(classes[i].token, sep)) { 95 info->class = i; 96 goto rock_on; 97 } 98 } 99 printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep); 100 info->class = PARPORT_CLASS_OTHER; 101 } else if (!strcmp(p, "CMD") || 102 !strcmp(p, "COMMAND SET")) { 103 kfree(info->cmdset); 104 info->cmdset = kstrdup(sep, GFP_KERNEL); 105 /* if it speaks printer language, it's 106 probably a printer */ 107 if (strstr(sep, "PJL") || strstr(sep, "PCL")) 108 guessed_class = PARPORT_CLASS_PRINTER; 109 } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) { 110 kfree(info->description); 111 info->description = kstrdup(sep, GFP_KERNEL); 112 } 113 } 114 rock_on: 115 if (q) 116 p = q + 1; 117 else 118 p = NULL; 119 } 120 121 /* If the device didn't tell us its class, maybe we have managed to 122 guess one from the things it did say. */ 123 if (info->class == PARPORT_CLASS_UNSPEC) 124 info->class = guessed_class; 125 126 pretty_print (port, device); 127 128 kfree(txt); 129 } 130 131 /* Get Std 1284 Device ID. */ 132 ssize_t parport_device_id (int devnum, char *buffer, size_t len) 133 { 134 ssize_t retval = -ENXIO; 135 struct pardevice *dev = parport_open (devnum, "Device ID probe", 136 NULL, NULL, NULL, 0, NULL); 137 if (!dev) 138 return -ENXIO; 139 140 parport_claim_or_block (dev); 141 142 /* Negotiate to compatibility mode, and then to device ID mode. 143 * (This is in case we are already in device ID mode.) */ 144 parport_negotiate (dev->port, IEEE1284_MODE_COMPAT); 145 retval = parport_negotiate (dev->port, 146 IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID); 147 148 if (!retval) { 149 int idlen; 150 unsigned char length[2]; 151 152 /* First two bytes are MSB,LSB of inclusive length. */ 153 retval = parport_read (dev->port, length, 2); 154 155 if (retval != 2) goto end_id; 156 157 idlen = (length[0] << 8) + length[1] - 2; 158 /* 159 * Check if the caller-allocated buffer is large enough 160 * otherwise bail out or there will be an at least off by one. 161 */ 162 if (idlen + 1 < len) 163 len = idlen; 164 else { 165 retval = -EINVAL; 166 goto out; 167 } 168 retval = parport_read (dev->port, buffer, len); 169 170 if (retval != len) 171 printk (KERN_DEBUG "%s: only read %Zd of %Zd ID bytes\n", 172 dev->port->name, retval, 173 len); 174 175 /* Some printer manufacturers mistakenly believe that 176 the length field is supposed to be _exclusive_. 177 In addition, there are broken devices out there 178 that don't even finish off with a semi-colon. */ 179 if (buffer[len - 1] != ';') { 180 ssize_t diff; 181 diff = parport_read (dev->port, buffer + len, 2); 182 retval += diff; 183 184 if (diff) 185 printk (KERN_DEBUG 186 "%s: device reported incorrect " 187 "length field (%d, should be %Zd)\n", 188 dev->port->name, idlen, retval); 189 else { 190 /* One semi-colon short of a device ID. */ 191 buffer[len++] = ';'; 192 printk (KERN_DEBUG "%s: faking semi-colon\n", 193 dev->port->name); 194 195 /* If we get here, I don't think we 196 need to worry about the possible 197 standard violation of having read 198 more than we were told to. The 199 device is non-compliant anyhow. */ 200 } 201 } 202 203 end_id: 204 buffer[len] = '\0'; 205 parport_negotiate (dev->port, IEEE1284_MODE_COMPAT); 206 } 207 208 if (retval > 2) 209 parse_data (dev->port, dev->daisy, buffer); 210 211 out: 212 parport_release (dev); 213 parport_close (dev); 214 return retval; 215 } 216