linux/drivers/parport/probe.c
<<
>>
Prefs
   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
  16static 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
  37static void pretty_print(struct parport *port, int device)
  38{
  39        struct parport_device_info *info = &port->probe_info[device + 1];
  40
  41        pr_info("%s", port->name);
  42
  43        if (device >= 0)
  44                pr_cont(" (addr %d)", device);
  45
  46        pr_cont(": %s", classes[info->class].descr);
  47        if (info->class)
  48                pr_cont(", %s %s", info->mfr, info->model);
  49
  50        pr_cont("\n");
  51}
  52
  53static 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                pr_warn("%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                                pr_warn("%s probe: warning, class '%s' not understood\n",
 102                                        port->name, sep);
 103                                info->class = PARPORT_CLASS_OTHER;
 104                        } else if (!strcmp(p, "CMD") ||
 105                                   !strcmp(p, "COMMAND SET")) {
 106                                kfree(info->cmdset);
 107                                info->cmdset = kstrdup(sep, GFP_KERNEL);
 108                                /* if it speaks printer language, it's
 109                                   probably a printer */
 110                                if (strstr(sep, "PJL") || strstr(sep, "PCL"))
 111                                        guessed_class = PARPORT_CLASS_PRINTER;
 112                        } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
 113                                kfree(info->description);
 114                                info->description = kstrdup(sep, GFP_KERNEL);
 115                        }
 116                }
 117        rock_on:
 118                if (q)
 119                        p = q + 1;
 120                else
 121                        p = NULL;
 122        }
 123
 124        /* If the device didn't tell us its class, maybe we have managed to
 125           guess one from the things it did say. */
 126        if (info->class == PARPORT_CLASS_UNSPEC)
 127                info->class = guessed_class;
 128
 129        pretty_print (port, device);
 130
 131        kfree(txt);
 132}
 133
 134/* Read up to count-1 bytes of device id. Terminate buffer with
 135 * '\0'. Buffer begins with two Device ID length bytes as given by
 136 * device. */
 137static ssize_t parport_read_device_id (struct parport *port, char *buffer,
 138                                       size_t count)
 139{
 140        unsigned char length[2];
 141        unsigned lelen, belen;
 142        size_t idlens[4];
 143        unsigned numidlens;
 144        unsigned current_idlen;
 145        ssize_t retval;
 146        size_t len;
 147
 148        /* First two bytes are MSB,LSB of inclusive length. */
 149        retval = parport_read (port, length, 2);
 150
 151        if (retval < 0)
 152                return retval;
 153        if (retval != 2)
 154                return -EIO;
 155
 156        if (count < 2)
 157                return 0;
 158        memcpy(buffer, length, 2);
 159        len = 2;
 160
 161        /* Some devices wrongly send LE length, and some send it two
 162         * bytes short. Construct a sorted array of lengths to try. */
 163        belen = (length[0] << 8) + length[1];
 164        lelen = (length[1] << 8) + length[0];
 165        idlens[0] = min(belen, lelen);
 166        idlens[1] = idlens[0]+2;
 167        if (belen != lelen) {
 168                int off = 2;
 169                /* Don't try lengths of 0x100 and 0x200 as 1 and 2 */
 170                if (idlens[0] <= 2)
 171                        off = 0;
 172                idlens[off] = max(belen, lelen);
 173                idlens[off+1] = idlens[off]+2;
 174                numidlens = off+2;
 175        }
 176        else {
 177                /* Some devices don't truly implement Device ID, but
 178                 * just return constant nibble forever. This catches
 179                 * also those cases. */
 180                if (idlens[0] == 0 || idlens[0] > 0xFFF) {
 181                        printk(KERN_DEBUG "%s: reported broken Device ID 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 while device told it would be %d bytes\n",
 205                                       port->name, len, belen);
 206                        }
 207                        goto done;
 208                }
 209
 210                /* This might end reading the Device ID too
 211                 * soon. Hopefully the needed fields were already in
 212                 * the first 256 bytes or so that we must have read so
 213                 * far. */
 214                if (buffer[len-1] == ';') {
 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",
 216                               port->name, current_idlen, numidlens,
 217                               length[0], length[1]);
 218                        goto done;
 219                }
 220        }
 221        if (current_idlen < numidlens) {
 222                /* Buffer not large enough, read to end of buffer. */
 223                size_t idlen, len2;
 224                if (len+1 < count) {
 225                        retval = parport_read (port, buffer+len, count-len-1);
 226                        if (retval < 0)
 227                                return retval;
 228                        len += retval;
 229                }
 230                /* Read the whole ID since some devices would not
 231                 * otherwise give back the Device ID from beginning
 232                 * next time when asked. */
 233                idlen = idlens[current_idlen];
 234                len2 = len;
 235                while(len2 < idlen && retval > 0) {
 236                        char tmp[4];
 237                        retval = parport_read (port, tmp,
 238                                               min(sizeof tmp, idlen-len2));
 239                        if (retval < 0)
 240                                return retval;
 241                        len2 += retval;
 242                }
 243        }
 244        /* In addition, there are broken devices out there that don't
 245           even finish off with a semi-colon. We do not need to care
 246           about those at this time. */
 247 done:
 248        buffer[len] = '\0';
 249        return len;
 250}
 251
 252/* Get Std 1284 Device ID. */
 253ssize_t parport_device_id (int devnum, char *buffer, size_t count)
 254{
 255        ssize_t retval = -ENXIO;
 256        struct pardevice *dev = parport_open(devnum, daisy_dev_name);
 257        if (!dev)
 258                return -ENXIO;
 259
 260        parport_claim_or_block (dev);
 261
 262        /* Negotiate to compatibility mode, and then to device ID
 263         * mode. (This so that we start form beginning of device ID if
 264         * already in device ID mode.) */
 265        parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
 266        retval = parport_negotiate (dev->port,
 267                                    IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
 268
 269        if (!retval) {
 270                retval = parport_read_device_id (dev->port, buffer, count);
 271                parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
 272                if (retval > 2)
 273                        parse_data (dev->port, dev->daisy, buffer+2);
 274        }
 275
 276        parport_release (dev);
 277        parport_close (dev);
 278        return retval;
 279}
 280