probe.c 5.9 KB

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