root/drivers/parport/probe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pretty_print
  2. parse_data
  3. parport_read_device_id
  4. parport_device_id

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

/* [<][>][^][v][top][bottom][index][help] */