probe.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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