Merge tag 'xfs-5.8-merge-9' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[platform/kernel/linux-starfive.git] / drivers / parport / probe.c
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         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
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                 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. */
137 static 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. */
253 ssize_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 }