~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/parport/probe.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.