probe.c 5.8 KB

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