]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/usb-darwin.c
Merge changes from CUPS 1.5svn-r8842.
[thirdparty/cups.git] / backend / usb-darwin.c
index a780d68beb597e76742a44e326ccec2fc12aea71..0fb993d83aa9bd29d6bef23e0c9bd0aa047ca45f 100644 (file)
@@ -1,7 +1,7 @@
 /*
-* "$Id: usb-darwin.c 7460 2008-04-16 02:19:54Z mike $"
+* "$Id: usb-darwin.c 7953 2008-09-17 01:43:19Z mike $"
 *
-* Copyright 2005-2008 Apple Inc. All rights reserved.
+* Copyright 2005-2009 Apple Inc. All rights reserved.
 *
 * IMPORTANT:  This Apple software is supplied to you by Apple Computer,
 * Inc. ("Apple") in consideration of your agreement to the following
 extern char **environ;
 
 
+/*
+ * DEBUG_WRITES, if defined, causes the backend to write data to the printer in
+ * 512 byte increments, up to 8192 bytes, to make debugging with a USB bus
+ * analyzer easier.
+ */
+
+#define DEBUG_WRITES 0
+
 /*
  * WAIT_EOF_DELAY is number of seconds we'll wait for responses from
  * the printer after we've finished sending all the data
@@ -232,6 +240,9 @@ typedef struct globals_s
 
   int                  print_fd;       /* File descriptor to print */
   ssize_t              print_bytes;    /* Print bytes read */
+#if DEBUG_WRITES
+  ssize_t              debug_bytes;    /* Current bytes to read */
+#endif /* DEBUG_WRITES */
 
   Boolean              wait_eof;
   int                  drain_output;   /* Drain all pending output */
@@ -279,9 +290,9 @@ static void soft_reset();
 static void status_timer_cb(CFRunLoopTimerRef timer, void *info);
 
 #if defined(__i386__) || defined(__x86_64__)
-static pid_t   child_pid;                                      /* Child PID */
+static pid_t   child_pid;              /* Child PID */
 static void run_legacy_backend(int argc, char *argv[], int fd);        /* Starts child backend process running as a ppc executable */
-static void sigterm_handler(int sig);                          /* SIGTERM handler */
+static void sigterm_handler(int sig);  /* SIGTERM handler */
 #endif /* __i386__ || __x86_64__ */
 
 #ifdef PARSE_PS_ERRORS
@@ -317,6 +328,7 @@ print_device(const char *uri,               /* I - Device URI */
 {
   char           serial[1024];         /* Serial number buffer */
   OSStatus       status;               /* Function results */
+  IOReturn       iostatus;             /* Current IO status */
   pthread_t      read_thread_id,       /* Read thread */
                  sidechannel_thread_id;/* Side-channel thread */
   int            have_sidechannel = 0; /* Was the side-channel thread started? */
@@ -582,13 +594,13 @@ print_device(const char *uri,             /* I - Device URI */
        {
          fputs("DEBUG: Received an interrupt before any bytes were "
                "written, aborting!\n", stderr);
-          return (0);
+          return (CUPS_BACKEND_OK);
        }
-       else if (errno != EAGAIN)
+       else if (errno != EAGAIN && errno != EINTR)
        {
          _cupsLangPuts(stderr, _("ERROR: Unable to read print data!\n"));
          perror("DEBUG: select");
-         return (CUPS_BACKEND_STOP);
+         return (CUPS_BACKEND_FAILED);
        }
       }
 
@@ -609,7 +621,16 @@ print_device(const char *uri,              /* I - Device URI */
 
       if (FD_ISSET(print_fd, &input_set))
       {
+#if DEBUG_WRITES
+       g.debug_bytes += 512;
+        if (g.debug_bytes > sizeof(print_buffer))
+         g.debug_bytes = 512;
+
+       g.print_bytes = read(print_fd, print_buffer, g.debug_bytes);
+
+#else
        g.print_bytes = read(print_fd, print_buffer, sizeof(print_buffer));
+#endif /* DEBUG_WRITES */
 
        if (g.print_bytes < 0)
        {
@@ -617,11 +638,11 @@ print_device(const char *uri,             /* I - Device URI */
          * Read error - bail if we don't see EAGAIN or EINTR...
          */
 
-         if (errno != EAGAIN || errno != EINTR)
+         if (errno != EAGAIN && errno != EINTR)
          {
            _cupsLangPuts(stderr, _("ERROR: Unable to read print data!\n"));
            perror("DEBUG: read");
-           return CUPS_BACKEND_STOP;
+           return (CUPS_BACKEND_FAILED);
          }
 
          g.print_bytes = 0;
@@ -643,41 +664,77 @@ print_device(const char *uri,             /* I - Device URI */
 
       if (g.print_bytes)
       {
-       bytes = g.print_bytes;
+       bytes    = g.print_bytes;
+       iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0);
 
-       status = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0);
+       /*
+       * Ignore timeout errors, but retain the number of bytes written to
+       * avoid sending duplicate data (<rdar://problem/6254911>)...
+       */
+
+       if (iostatus == kIOUSBTransactionTimeout)
+       {
+         fputs("DEBUG: Got USB transaction timeout during write!\n", stderr);
+         iostatus = 0;
+       }
 
        /*
-       * Ignore timeout errors...
+        * If we've stalled, retry the write...
        */
 
-       if (status == kIOUSBTransactionTimeout)
+       else if (iostatus == kIOUSBPipeStalled)
        {
-         status = 0;
-         bytes = 0;
+         fputs("DEBUG: Got USB pipe stalled during write!\n", stderr);
+
+         bytes    = g.print_bytes;
+         iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0);
        }
 
-       if (status || bytes < 0)
+       /*
+       * Retry a write after an aborted write since we probably just got
+       * SIGTERM (<rdar://problem/6860126>)...
+       */
+
+       else if (iostatus == kIOReturnAborted)
+       {
+         fputs("DEBUG: Got return aborted during write!\n", stderr);
+
+         IOReturn err = (*g.classdriver)->Abort(g.classdriver);
+         fprintf(stderr, "DEBUG: USB class driver Abort returned %x\n", err);
+
+#if DEBUG_WRITES
+          sleep(5);
+#endif /* DEBUG_WRITES */
+
+         bytes    = g.print_bytes;
+         iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0);
+        }
+
+       if (iostatus || bytes < 0)
        {
         /*
          * Write error - bail if we don't see an error we can retry...
          */
 
-         OSStatus err = (*g.classdriver)->Abort(g.classdriver);
          _cupsLangPuts(stderr, _("ERROR: Unable to send print data!\n"));
-         fprintf(stderr, "DEBUG: USB class driver WritePipe returned %ld\n",
-                 (long)status);
-         fprintf(stderr, "DEBUG: USB class driver Abort returned %ld\n",
-                 (long)err);
-         status = CUPS_BACKEND_STOP;
+         fprintf(stderr, "DEBUG: USB class driver WritePipe returned %x\n",
+                 iostatus);
+
+         IOReturn err = (*g.classdriver)->Abort(g.classdriver);
+         fprintf(stderr, "DEBUG: USB class driver Abort returned %x\n",
+                 err);
+
+         status = CUPS_BACKEND_FAILED;
          break;
        }
+       else if (bytes > 0)
+       {
+         fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);
 
-        fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);
-
-        g.print_bytes -= bytes;
-       print_ptr   += bytes;
-       total_bytes += bytes;
+         g.print_bytes -= bytes;
+         print_ptr   += bytes;
+         total_bytes += bytes;
+       }
       }
 
       if (print_fd != 0 && status == noErr)
@@ -757,6 +814,7 @@ print_device(const char *uri,               /* I - Device URI */
       * Force the read thread to exit...
       */
 
+      g.wait_eof = 0;
       pthread_kill(read_thread_id, SIGTERM);
     }
   }
@@ -822,6 +880,8 @@ static void *read_thread(void *reference)
     readstatus = (*g.classdriver)->ReadPipe(g.classdriver, readbuffer, &rbytes);
     if (readstatus == kIOReturnSuccess && rbytes > 0)
     {
+      fprintf(stderr, "DEBUG: Read %d bytes of back-channel data...\n",
+              (int)rbytes);
       cupsBackChannelWrite((char*)readbuffer, rbytes, 1.0);
 
       /* cntrl-d is echoed by the printer.
@@ -836,6 +896,12 @@ static void *read_thread(void *reference)
       parse_pserror(readbuffer, rbytes);
 #endif
     }
+    else if (readstatus == kIOUSBTransactionTimeout)
+      fputs("DEBUG: Got USB transaction timeout during write!\n", stderr);
+    else if (readstatus == kIOUSBPipeStalled)
+      fputs("DEBUG: Got USB pipe stalled during read!\n", stderr);
+    else if (readstatus == kIOReturnAborted)
+      fputs("DEBUG: Got return aborted during read!\n", stderr);
 
    /*
     * Make sure this loop executes no more than once every 250 miliseconds...
@@ -877,46 +943,88 @@ sidechannel_thread(void *reference)
     datalen = sizeof(data);
 
     if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
-      continue;
+      break;
 
     switch (command)
     {
       case CUPS_SC_CMD_SOFT_RESET:     /* Do a soft reset */
+         fputs("DEBUG: CUPS_SC_CMD_SOFT_RESET received from driver...\n",
+               stderr);
+
           if ((*g.classdriver)->SoftReset != NULL)
          {
            soft_reset();
            cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, NULL, 0, 1.0);
+           fputs("DEBUG: Returning status CUPS_STATUS_OK with no bytes...\n",
+                 stderr);
          }
          else
          {
            cupsSideChannelWrite(command, CUPS_SC_STATUS_NOT_IMPLEMENTED,
                                 NULL, 0, 1.0);
+           fputs("DEBUG: Returning status CUPS_STATUS_NOT_IMPLEMENTED with "
+                 "no bytes...\n", stderr);
          }
          break;
 
       case CUPS_SC_CMD_DRAIN_OUTPUT:   /* Drain all pending output */
+         fputs("DEBUG: CUPS_SC_CMD_DRAIN_OUTPUT received from driver...\n",
+               stderr);
+
          g.drain_output = 1;
          break;
 
       case CUPS_SC_CMD_GET_BIDI:               /* Is the connection bidirectional? */
+         fputs("DEBUG: CUPS_SC_CMD_GET_BIDI received from driver...\n",
+               stderr);
+
          data[0] = g.bidi_flag;
          cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, 1, 1.0);
+
+         fprintf(stderr,
+                 "DEBUG: Returned CUPS_SC_STATUS_OK with 1 byte (%02X)...\n",
+                 data[0]);
          break;
 
       case CUPS_SC_CMD_GET_DEVICE_ID:  /* Return IEEE-1284 device ID */
+         fputs("DEBUG: CUPS_SC_CMD_GET_DEVICE_ID received from driver...\n",
+               stderr);
+
          datalen = sizeof(data);
          get_device_id(&status, data, &datalen);
          cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, datalen, 1.0);
+
+          if (datalen < sizeof(data))
+           data[datalen] = '\0';
+         else
+           data[sizeof(data) - 1] = '\0';
+
+         fprintf(stderr,
+                 "DEBUG: Returning CUPS_SC_STATUS_OK with %d bytes (%s)...\n",
+                 datalen, data);
          break;
 
       case CUPS_SC_CMD_GET_STATE:              /* Return device state */
+         fputs("DEBUG: CUPS_SC_CMD_GET_STATE received from driver...\n",
+               stderr);
+
          data[0] = CUPS_SC_STATE_ONLINE;
          cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, 1, 1.0);
+
+         fprintf(stderr,
+                 "DEBUG: Returned CUPS_SC_STATUS_OK with 1 byte (%02X)...\n",
+                 data[0]);
          break;
 
       default:
+         fprintf(stderr, "DEBUG: Unknown side-channel command (%d) received "
+                         "from driver...\n", command);
+
          cupsSideChannelWrite(command, CUPS_SC_STATUS_NOT_IMPLEMENTED,
                               NULL, 0, 1.0);
+
+         fputs("DEBUG: Returned CUPS_SC_STATUS_NOT_IMPLEMENTED with no bytes...\n",
+               stderr);
          break;
     }
   }
@@ -1036,11 +1144,13 @@ static Boolean list_device_cb(void *refcon,
 
       modelstr[0] = '/';
 
-      if (!CFStringGetCString(make, makestr, sizeof(makestr),
+      if (!make ||
+          !CFStringGetCString(make, makestr, sizeof(makestr),
                              kCFStringEncodingUTF8))
         strcpy(makestr, "Unknown");
 
-      if (!CFStringGetCString(model, &modelstr[1], sizeof(modelstr)-1,
+      if (!model ||
+          !CFStringGetCString(model, &modelstr[1], sizeof(modelstr)-1,
                              kCFStringEncodingUTF8))
         strcpy(modelstr + 1, "Printer");
 
@@ -1054,7 +1164,7 @@ static Boolean list_device_cb(void *refcon,
        snprintf(optionsstr, sizeof(optionsstr), "?location=%x", (unsigned)deviceLocation);
 
       httpAssembleURI(HTTP_URI_CODING_ALL, uristr, sizeof(uristr), "usb", NULL, makestr, 0, modelstr);
-      strncat(uristr, optionsstr, sizeof(uristr));
+      strlcat(uristr, optionsstr, sizeof(uristr));
 
       cupsBackendReport("direct", uristr, make_modelstr, make_modelstr, idstr,
                         NULL);
@@ -1193,18 +1303,10 @@ static void copy_deviceinfo(CFStringRef deviceIDString,
   CFStringRef serialKeys[] = { CFSTR("SN:"),  CFSTR("SERN:"), NULL };
 
   if (make != NULL)
-  {
-    if ((*make = copy_value_for_key(deviceIDString, makeKeys)) == NULL)
-      *make = CFStringCreateWithCString(kCFAllocatorDefault, "Unknown",
-                                        kCFStringEncodingUTF8);
-  }
+    *make = copy_value_for_key(deviceIDString, makeKeys);
 
   if (model != NULL)
-  {
-    if ((*model = copy_value_for_key(deviceIDString, modelKeys)) == NULL)
-      *model = CFStringCreateWithCString(kCFAllocatorDefault, "Printer",
-                                         kCFStringEncodingUTF8);
-  }
+    *model = copy_value_for_key(deviceIDString, modelKeys);
 
   if (serial != NULL)
     *serial = copy_value_for_key(deviceIDString, serialKeys);
@@ -1248,58 +1350,83 @@ static kern_return_t load_classdriver(CFStringRef           driverPath,
                                      printer_interface_t   intf,
                                      classdriver_t         ***printerDriver)
 {
-  kern_return_t kr = kUSBPrinterClassDeviceNotOpen;
-  classdriver_t **driver = NULL;
-  CFStringRef bundle = (driverPath == NULL ? kUSBGenericTOPrinterClassDriver : driverPath);
+  kern_return_t        kr = kUSBPrinterClassDeviceNotOpen;
+  classdriver_t        **driver = NULL;
+  CFStringRef  bundle = driverPath ? driverPath : kUSBGenericTOPrinterClassDriver;
+  char                 bundlestr[1024];        /* Bundle path */
+  struct stat  bundleinfo;             /* File information for bundle */
+  CFURLRef     url;                    /* URL for driver */
+  CFPlugInRef  plugin = NULL;          /* Plug-in address */
+
+
+  CFStringGetCString(bundle, bundlestr, sizeof(bundlestr), kCFStringEncodingUTF8);
 
-  if (bundle != NULL)
+ /*
+  * Validate permissions for the class driver...
+  */
+
+  if (stat(bundlestr, &bundleinfo))
+  {
+    fprintf(stderr, "DEBUG: Unable to load class driver \"%s\": %s\n",
+           bundlestr, strerror(errno));
+    return (kr);
+  }
+  else if (bundleinfo.st_mode & S_IWOTH)
   {
-    CFURLRef url = CFURLCreateWithFileSystemPath(NULL, bundle, kCFURLPOSIXPathStyle, true);
-    CFPlugInRef plugin = (url != NULL ? CFPlugInCreate(NULL, url) : NULL);
+    fprintf(stderr, "DEBUG: Unable to load class driver \"%s\": insecure file "
+                   "permissions (0%o)\n", bundlestr, bundleinfo.st_mode);
+    return (kr);
+  }
+
+ /*
+  * Try loading the class driver...
+  */
 
-    if (url != NULL)
-      CFRelease(url);
+  url = CFURLCreateWithFileSystemPath(NULL, bundle, kCFURLPOSIXPathStyle, true);
 
-    if (plugin != NULL)
+  if (url)
+  {
+    plugin = CFPlugInCreate(NULL, url);
+    CFRelease(url);
+  }
+  else
+    plugin = NULL;
+
+  if (plugin)
+  {
+    CFArrayRef factories = CFPlugInFindFactoriesForPlugInTypeInPlugIn(kUSBPrinterClassTypeID, plugin);
+    if (factories != NULL && CFArrayGetCount(factories) > 0)
     {
-      CFArrayRef factories = CFPlugInFindFactoriesForPlugInTypeInPlugIn(kUSBPrinterClassTypeID, plugin);
-      if (factories != NULL && CFArrayGetCount(factories) > 0)
+      CFUUIDRef factoryID = CFArrayGetValueAtIndex(factories, 0);
+      IUnknownVTbl **iunknown = CFPlugInInstanceCreate(NULL, factoryID, kUSBPrinterClassTypeID);
+      if (iunknown != NULL)
       {
-       CFUUIDRef factoryID = CFArrayGetValueAtIndex(factories, 0);
-       IUnknownVTbl **iunknown = CFPlugInInstanceCreate(NULL, factoryID, kUSBPrinterClassTypeID);
-       if (iunknown != NULL)
+       kr = (*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(kUSBPrinterClassInterfaceID), (LPVOID *)&driver);
+       if (kr == kIOReturnSuccess && driver != NULL)
        {
-         kr = (*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(kUSBPrinterClassInterfaceID), (LPVOID *)&driver);
-         if (kr == kIOReturnSuccess && driver != NULL)
-         {
-           classdriver_t **genericDriver = NULL;
-           if (driverPath != NULL && CFStringCompare(driverPath, kUSBGenericTOPrinterClassDriver, 0) != kCFCompareEqualTo)
-             kr = load_classdriver(NULL, intf, &genericDriver);
+         classdriver_t **genericDriver = NULL;
+         if (driverPath != NULL && CFStringCompare(driverPath, kUSBGenericTOPrinterClassDriver, 0) != kCFCompareEqualTo)
+           kr = load_classdriver(NULL, intf, &genericDriver);
 
-           if (kr == kIOReturnSuccess)
-           {
-             (*driver)->interface = intf;
-             (*driver)->Initialize(driver, genericDriver);
+         if (kr == kIOReturnSuccess)
+         {
+           (*driver)->interface = intf;
+           (*driver)->Initialize(driver, genericDriver);
 
-             (*driver)->plugin = plugin;
-             (*driver)->interface = intf;
-             *printerDriver = driver;
-           }
+           (*driver)->plugin = plugin;
+           (*driver)->interface = intf;
+           *printerDriver = driver;
          }
-         (*iunknown)->Release(iunknown);
        }
-       CFRelease(factories);
+       (*iunknown)->Release(iunknown);
       }
+      CFRelease(factories);
     }
   }
 
-#ifdef DEBUG
-  char bundlestr[1024];
-  CFStringGetCString(bundle, bundlestr, sizeof(bundlestr), kCFStringEncodingUTF8);
   fprintf(stderr, "DEBUG: load_classdriver(%s) (kr:0x%08x)\n", bundlestr, (int)kr);
-#endif /* DEBUG */
 
-  return kr;
+  return (kr);
 }
 
 
@@ -1722,7 +1849,7 @@ static void setup_cfLanguage(void)
     lang[0] = CFStringCreateWithCString(kCFAllocatorDefault, requestedLang, kCFStringEncodingUTF8);
     langArray = CFArrayCreate(kCFAllocatorDefault, (const void **)lang, sizeof(lang) / sizeof(lang[0]), &kCFTypeArrayCallBacks);
 
-    CFPreferencesSetAppValue(CFSTR("AppleLanguages"), langArray, kCFPreferencesCurrentApplication);
+    CFPreferencesSetValue(CFSTR("AppleLanguages"), langArray, kCFPreferencesCurrentApplication, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
     fprintf(stderr, "DEBUG: usb: AppleLanguages=\"%s\"\n", requestedLang);
 
     CFRelease(lang[0]);
@@ -1777,6 +1904,9 @@ static void run_legacy_backend(int argc,
     struct sigaction   action;         /* POSIX signal action */
     sigset_t           newmask,        /* New signal mask */
                        oldmask;        /* Old signal mask */
+    char               usbpath[1024];  /* Path to USB backend */
+    const char         *cups_serverbin;/* Path to CUPS binaries */
+
 
     memset(&action, 0, sizeof(action));
     sigaddset(&action.sa_mask, SIGTERM);
@@ -1811,8 +1941,8 @@ static void run_legacy_backend(int argc,
 
     if (!posix_spawnattr_init(&attrs))
     {
-      posix_spawnattr_setsigdefault(attrs, &oldmask);
-      if (posix_spawnattr_setbinpref_np(attrs, 1, &cpu, &ocount) || ocount != 1)
+      posix_spawnattr_setsigdefault(&attrs, &oldmask);
+      if (posix_spawnattr_setbinpref_np(&attrs, 1, &cpu, &ocount) || ocount != 1)
       {
 #  ifdef __x86_64__
        perror("DEBUG: Unable to set binary preference to i386");
@@ -1828,15 +1958,19 @@ static void run_legacy_backend(int argc,
     * Set up the arguments and call posix_spawn...
     */
 
+    if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
+      cups_serverbin = CUPS_SERVERBIN;
+    snprintf(usbpath, sizeof(usbpath), "%s/backend/usb", cups_serverbin);
+
     for (i = 0; i < argc && i < (sizeof(my_argv) / sizeof(my_argv[0])) - 1; i ++)
       my_argv[i] = argv[i];
 
     my_argv[i] = NULL;
 
-    if (posix_spawn(&child_pid, "/usr/libexec/cups/backend/usb", NULL, &attrs,
-                    my_argv, environ))
+    if (posix_spawn(&child_pid, usbpath, NULL, &attrs, my_argv, environ))
     {
-      perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb");
+      fprintf(stderr, "DEBUG: Unable to exec %s: %s\n", usbpath,
+              strerror(errno));
       _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n"));
       exit(CUPS_BACKEND_STOP);
     }
@@ -1890,14 +2024,32 @@ static void run_legacy_backend(int argc,
  * 'sigterm_handler()' - SIGTERM handler.
  */
 
-static void sigterm_handler(int sig)
+static void
+sigterm_handler(int sig)               /* I - Signal */
 {
   /* If we started a child process pass the signal on to it...
    */
   if (child_pid)
+  {
+   /*
+    * If we started a child process pass the signal on to it...
+    */
+
+    int        status;
+
     kill(child_pid, sig);
+    while (waitpid(child_pid, &status, 0) < 0 && errno == EINTR);
 
-  exit(1);
+    if (WIFEXITED(status))
+      exit(WEXITSTATUS(status));
+    else if (status == SIGTERM || status == SIGKILL)
+      exit(0);
+    else
+    {
+      fprintf(stderr, "DEBUG: Child crashed on signal %d!\n", status);
+      exit(CUPS_BACKEND_STOP);
+    }
+  }
 }
 
 #endif /* __i386__ || __x86_64__ */
@@ -2051,12 +2203,11 @@ static void get_device_id(cups_sc_status_t *status,
                          char *data,
                          int *datalen)
 {
-  UInt32 deviceLocation = 0;
-  UInt8        interfaceNum = 0;
   CFStringRef deviceIDString = NULL;
 
   /* GetDeviceID */
-  copy_devicestring(g.printer_obj, &deviceIDString, &deviceLocation, &interfaceNum);
+  copy_deviceid(g.classdriver, &deviceIDString);
+
   if (deviceIDString)
   {
     CFStringGetCString(deviceIDString, data, *datalen, kCFStringEncodingUTF8);
@@ -2068,5 +2219,5 @@ static void get_device_id(cups_sc_status_t *status,
 
 
 /*
- * End of "$Id: usb-darwin.c 7460 2008-04-16 02:19:54Z mike $".
+ * End of "$Id: usb-darwin.c 7953 2008-09-17 01:43:19Z mike $".
  */