diff --git a/backend/Makefile.am b/backend/Makefile.am
index 0b0fd65..ba66c54 100644
--- a/backend/Makefile.am
+++ b/backend/Makefile.am
@@ -774,14 +774,15 @@ libsane_niash_la_LIBADD = $(COMMON_LIBS) libniash.la ../sanei/sanei_init_debug.l
 # TODO: Why are these distributed but not compiled?
 EXTRA_DIST += niash_core.c niash_core.h niash_xfer.c niash_xfer.h
 
-libpie_la_SOURCES = pie.c pie-scsidef.h
+libpie_la_SOURCES = pie.c pie.h pie-scsidef.h
 libpie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie
 
 nodist_libsane_pie_la_SOURCES = pie-s.c 
 libsane_pie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie
 libsane_pie_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
-libsane_pie_la_LIBADD = $(COMMON_LIBS) libpie.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
-EXTRA_DIST += pie.conf.in
+libsane_pie_la_LIBADD = $(COMMON_LIBS) libpie.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) $(USB_LIBS)
+# plus included files
+EXTRA_DIST += pie.conf.in pie_usb.c
 
 libp5_la_SOURCES = p5.c p5.h p5_device.h
 libp5_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=p5
diff --git a/backend/pie.c b/backend/pie.c
index 941ed62..dcf28ec 100644
--- a/backend/pie.c
+++ b/backend/pie.c
@@ -86,6 +86,7 @@
 #include "../include/sane/sanei.h"
 #include "../include/sane/saneopts.h"
 #include "../include/sane/sanei_scsi.h"
+#include "../include/sane/sanei_usb.h"
 #include "../include/sane/sanei_debug.h"
 
 #define BACKEND_NAME	pie
@@ -95,45 +96,7 @@
 # include "../include/sane/sanei_thread.h"
 
 #include "pie-scsidef.h"
-
-#define DBG_error0  0
-#define DBG_error   1
-#define DBG_sense   2
-#define DBG_warning 3
-#define DBG_inquiry 4
-
-#define DBG_info    5
-#define DBG_info2   6
-#define DBG_proc    7
-#define DBG_read    8
-#define DBG_sane_init   10
-#define DBG_sane_proc   11
-#define DBG_sane_info   12
-#define DBG_sane_option 13
-#define DBG_dump	14
-
-#define BUILD 9
-
-#define PIE_CONFIG_FILE "pie.conf"
-
-#define LINEART_STR         SANE_VALUE_SCAN_MODE_LINEART
-#define HALFTONE_STR        SANE_VALUE_SCAN_MODE_HALFTONE
-#define GRAY_STR            SANE_VALUE_SCAN_MODE_GRAY
-#define COLOR_STR           SANE_VALUE_SCAN_MODE_COLOR
-
-#define LINEART             1
-#define HALFTONE            2
-#define GRAYSCALE           3
-#define RGB                 4
-
-#define CAL_MODE_PREVIEW        (INQ_CAP_FAST_PREVIEW)
-#define CAL_MODE_FLATBED        0x00
-#define CAL_MODE_ADF            (INQ_OPT_DEV_ADF)
-#define CAL_MODE_TRANPSARENCY   (INQ_OPT_DEV_TP)
-#define CAL_MODE_TRANPSARENCY1  (INQ_OPT_DEV_TP1)
-
-#define min(a,b) (((a)<(b))?(a):(b))
-#define max(a,b) (((a)>(b))?(a):(b))
+#include "pie.h"
 
 
 /* names of scanners that are supported because */
@@ -157,173 +120,11 @@ static char *scanner_str[] = {
   "PIE", "ScanAce 636S",
   "AdLib", "JetScan 630",
   "AdLib", "JetScan 636PRO",
+  /* USB film scanners */
+  "PIE", "SF Scanner",
   "END_OF_LIST"
 };
 
-/* times (in us) to delay after certain commands. Scanner seems to lock up if it returns busy
- * status and commands are repeatedly reissued (by kernel error handler) */
-
-#define DOWNLOAD_GAMMA_WAIT_TIME	(1000000)
-#define SCAN_WAIT_TIME			(1000000)
-#define SCAN_WARMUP_WAIT_TIME		(500000)
-#define TUR_WAIT_TIME			(500000)
-
-
-/* options supported by the scanner */
-
-enum Pie_Option
-{
-  OPT_NUM_OPTS = 0,
-
-  /* ------------------------------------------- */
-  OPT_MODE_GROUP,
-  OPT_MODE,
-  OPT_RESOLUTION,
-
-
-  /* ------------------------------------------- */
-
-  OPT_GEOMETRY_GROUP,
-  OPT_TL_X,			/* top-left x */
-  OPT_TL_Y,			/* top-left y */
-  OPT_BR_X,			/* bottom-right x */
-  OPT_BR_Y,			/* bottom-right y */
-
-  /* ------------------------------------------- */
-
-  OPT_ENHANCEMENT_GROUP,
-
-  OPT_HALFTONE_PATTERN,
-  OPT_SPEED,
-  OPT_THRESHOLD,
-
-  OPT_GAMMA_VECTOR,
-  OPT_GAMMA_VECTOR_R,
-  OPT_GAMMA_VECTOR_G,
-  OPT_GAMMA_VECTOR_B,
-
-  /* ------------------------------------------- */
-
-  OPT_ADVANCED_GROUP,
-  OPT_PREVIEW,
-
-  /* must come last: */
-  NUM_OPTIONS
-};
-
-
-
-
-/* This defines the information needed during calibration */
-
-struct Pie_cal_info
-{
-  int cal_type;
-  int receive_bits;
-  int send_bits;
-  int num_lines;
-  int pixels_per_line;
-};
-
-
-/* This structure holds the information about a physical scanner */
-
-typedef struct Pie_Device
-{
-  struct Pie_Device *next;
-
-  char *devicename;		/* name of the scanner device */
-
-  char vendor[9];		/* will be xxxxx */
-  char product[17];		/* e.g. "SuperVista_S12" or so */
-  char version[5];		/* e.g. V1.3 */
-
-  SANE_Device sane;
-  SANE_Range dpi_range;
-  SANE_Range x_range;
-  SANE_Range y_range;
-
-  SANE_Range exposure_range;
-  SANE_Range shadow_range;
-  SANE_Range highlight_range;
-
-  int inquiry_len;		/* length of inquiry return block */
-
-  int inquiry_x_res;		/* maximum x-resolution */
-  int inquiry_y_res;		/* maximum y-resolution */
-  int inquiry_pixel_resolution;
-  double inquiry_fb_width;	/* flatbed width in inches */
-  double inquiry_fb_length;	/* flatbed length in inches */
-
-  int inquiry_trans_top_left_x;
-  int inquiry_trans_top_left_y;
-  double inquiry_trans_width;	/* transparency width in inches */
-  double inquiry_trans_length;	/* transparency length in inches */
-
-  int inquiry_halftones;	/* number of halftones supported */
-  int inquiry_filters;		/* available colour filters */
-  int inquiry_color_depths;	/* available colour depths */
-  int inquiry_color_format;	/* colour format from scanner */
-  int inquiry_image_format;	/* image data format */
-  int inquiry_scan_capability;	/* additional scanner features, number of speeds */
-  int inquiry_optional_devices;	/* optional devices */
-  int inquiry_enhancements;	/* enhancements */
-  int inquiry_gamma_bits;	/* no of bits used for gamma table */
-  int inquiry_fast_preview_res;	/* fast preview resolution */
-  int inquiry_min_highlight;	/* min highlight % that can be used */
-  int inquiry_max_shadow;	/* max shadow % that can be used */
-  int inquiry_cal_eqn;		/* which calibration equation to use */
-  int inquiry_min_exp;		/* min exposure % */
-  int inquiry_max_exp;		/* max exposure % */
-
-  SANE_String scan_mode_list[7];	/* holds names of types of scan (color, ...) */
-
-  SANE_String halftone_list[17];	/* holds the names of the halftone patterns from the scanner */
-
-  SANE_String speed_list[9];	/* holds the names of available speeds */
-
-  int cal_info_count;		/* number of calibration info sets */
-  struct Pie_cal_info *cal_info;	/* points to the actual calibration information */
-}
-Pie_Device;
-
-/* This structure holds information about an instance of an 'opened' scanner */
-
-typedef struct Pie_Scanner
-{
-  struct Pie_Scanner *next;
-  Pie_Device *device;		/* pointer to physical scanner */
-
-  int sfd;			/* scanner file desc. */
-  int bufsize;			/* max scsi buffer size */
-
-  SANE_Option_Descriptor opt[NUM_OPTIONS];	/* option descriptions for this instance */
-  Option_Value val[NUM_OPTIONS];	/* option settings for this instance */
-  SANE_Int *gamma_table[4];	/* gamma tables for this instance */
-  SANE_Range gamma_range;
-  int gamma_length;		/* size of gamma table */
-
-  int scanning;			/* true if actually doing a scan */
-  SANE_Parameters params;
-
-  SANE_Pid reader_pid;
-  int pipe;
-  int reader_fds;
-  
-  int colormode;		/* whether RGB, GRAY, LINEART, HALFTONE */
-  int resolution;
-  int cal_mode;			/* set to value to compare cal_info mode to */
-
-  int cal_filter;		/* set to indicate which filters will provide data for cal */
-
-  int filter_offset1;		/* offsets between colors in indexed scan mode */
-  int filter_offset2;
-
-  int bytes_per_line;		/* number of bytes per line */
-
-}
-Pie_Scanner;
-
 static const SANE_Range percentage_range_100 = {
   0 << SANE_FIXED_SCALE_SHIFT,	/* minimum */
   100 << SANE_FIXED_SCALE_SHIFT,	/* maximum */
@@ -338,6 +139,9 @@ static const SANE_Device **devlist = NULL;
 
 static SANE_Status pie_wait_scanner (Pie_Scanner * scanner);
 
+/* USB code is included here to allow static qualifiers */
+
+#include "pie_usb.c"
 
 /* ---------------------------------- PIE DUMP_BUFFER ---------------------------------- */
 
@@ -369,23 +173,32 @@ pie_dump_buffer (int level, unsigned char *buf, int n)
 /* ---------------------------------- PIE INIT ---------------------------------- */
 
 static void
-pie_init (Pie_Device * dev)	/* pie_init is called once while driver-initialization */
+pie_init (Pie_Device * dev, SANE_Int model)	/* pie_init is called once while driver-initialization */
 {
   DBG (DBG_proc, "init\n");
 
+  dev->model = model;
   dev->cal_info_count = 0;
   dev->cal_info = NULL;
 
   dev->devicename = NULL;
   dev->inquiry_len = 0;
 
+  if (model == 0)
+    {
 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
-  DBG (DBG_info,
-       "variable scsi buffer size (usage of sanei_scsi_open_extended)\n");
+      DBG (DBG_info,
+           "variable scsi buffer size (usage of sanei_scsi_open_extended)\n");
 #else
-  DBG (DBG_info, "fixed scsi buffer size = %d bytes\n",
-       sanei_scsi_max_request_size);
+      DBG (DBG_info, "fixed scsi buffer size = %d bytes\n",
+           sanei_scsi_max_request_size);
 #endif
+      pie_scsi_cmd = sanei_scsi_cmd;
+    }
+  else
+    {
+      pie_scsi_cmd = pie_usb_scsi_wrapper;
+    }
 }
 
 
@@ -824,7 +637,7 @@ pie_do_inquiry (int sfd, unsigned char *buffer)
   size = 5;
 
   set_inquiry_return_size (inquiry.cmd, size);	/* first get only 5 bytes to get size of inquiry_return_block */
-  status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size);
+  status = (*pie_scsi_cmd) (sfd, inquiry.cmd, inquiry.size, buffer, &size);
   if (status)
     {
       DBG (DBG_error, "pie_do_inquiry: command returned status %s\n",
@@ -834,7 +647,7 @@ pie_do_inquiry (int sfd, unsigned char *buffer)
   size = get_inquiry_additional_length (buffer) + 5;
 
   set_inquiry_return_size (inquiry.cmd, size);	/* then get inquiry with actual size */
-  status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size);
+  status = (*pie_scsi_cmd) (sfd, inquiry.cmd, inquiry.size, buffer, &size);
   if (status)
     {
       DBG (DBG_error, "pie_do_inquiry: command returned status %s\n",
@@ -975,7 +788,7 @@ pie_get_halftones (Pie_Device * dev, int sfd)
       set_data_length (data, 2);
       data[4] = i;
 
-      status = sanei_scsi_cmd (sfd, buffer, swrite.size + size, NULL, NULL);
+      status = (*pie_scsi_cmd) (sfd, buffer, swrite.size + size, NULL, NULL);
       if (status)
 	{
 	  DBG (DBG_error,
@@ -991,7 +804,7 @@ pie_get_halftones (Pie_Device * dev, int sfd)
 	  set_read_length (sread.cmd, size);
 
 	  DBG (DBG_info, "doing read\n");
-	  status = sanei_scsi_cmd (sfd, sread.cmd, sread.size, buffer, &size);
+	  status = (*pie_scsi_cmd) (sfd, sread.cmd, sread.size, buffer, &size);
 	  if (status)
 	    {
 	      DBG (DBG_error,
@@ -1039,7 +852,7 @@ pie_get_cal_info (Pie_Device * dev, int sfd)
 
   set_command (data, READ_CAL_INFO);
 
-  status = sanei_scsi_cmd (sfd, buffer, swrite.size + size, NULL, NULL);
+  status = (*pie_scsi_cmd) (sfd, buffer, swrite.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error, "pie_get_cal_info: write command returned status %s\n",
@@ -1054,7 +867,7 @@ pie_get_cal_info (Pie_Device * dev, int sfd)
       set_read_length (sread.cmd, size);
 
       DBG (DBG_info, "doing read\n");
-      status = sanei_scsi_cmd (sfd, sread.cmd, sread.size, buffer, &size);
+      status = (*pie_scsi_cmd) (sfd, sread.cmd, sread.size, buffer, &size);
       if (status)
 	{
 	  DBG (DBG_error,
@@ -1088,14 +901,63 @@ pie_get_cal_info (Pie_Device * dev, int sfd)
     }
 }
 
+
+/* ---------------------------- PIE_SCSI_ATTACH_OPEN -------------------------- */
+
+static SANE_Status
+pie_scsi_attach_open (SANE_String_Const devicename, int * sfd, Pie_Device * dev)
+{
+  int bufsize;
+
+  DBG (DBG_info, "pie_scsi_attach_open: opening `%s'\n", devicename);
+
+#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
+  bufsize = 16384;		/* 16KB */
+
+  if (sanei_scsi_open_extended
+      (devicename, sfd, sense_handler, dev, &bufsize) != 0)
+    {
+      DBG (DBG_warning, "pie_scsi_attach_open: sanei_scsi_open_extended failed\n");
+      return SANE_STATUS_INVAL;
+    }
+
+  if (bufsize < 4096)		/* < 4KB */
+    {
+      DBG (DBG_error,
+	   "pie_scsi_attach_open: sanei_scsi_open_extended returned too small scsi buffer (%d)\n",
+	   bufsize);
+      sanei_scsi_close (*sfd);
+      return SANE_STATUS_NO_MEM;
+    }
+
+  DBG (DBG_info,
+       "pie_scsi_attach_open: sanei_scsi_open_extended returned scsi buffer size = %d\n",
+       bufsize);
+#else
+  bufsize = sanei_scsi_max_request_size;
+
+  if (sanei_scsi_open (devicename, &sfd, sense_handler, dev) != 0)
+    {
+      DBG (DBG_warning, "pie_scsi_attach_open: sanei_scsi_open failed\n");
+
+      return SANE_STATUS_INVAL;
+    }
+#endif
+
+  DBG (DBG_info, "pie_scsi_attach_open: SCSI device `%s' successfully opened\n", devicename);
+
+  return SANE_STATUS_GOOD;
+}
+
 /* ------------------------------- ATTACH SCANNER ----------------------------- */
 
 static SANE_Status
 attach_scanner (const char *devicename, Pie_Device ** devp)
 {
+  SANE_Status status;
+  SANE_Int model = 0;		/* assume SCSI scanner: model = 0 */
   Pie_Device *dev;
   int sfd;
-  int bufsize;
 
   DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename);
 
@@ -1117,46 +979,21 @@ attach_scanner (const char *devicename, Pie_Device ** devp)
       return SANE_STATUS_NO_MEM;
     }
 
-  DBG (DBG_info, "attach_scanner: opening %s\n", devicename);
-
-#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
-  bufsize = 16384;		/* 16KB */
-
-  if (sanei_scsi_open_extended
-      (devicename, &sfd, sense_handler, dev, &bufsize) != 0)
+  status = pie_scsi_attach_open (devicename, &sfd, dev);
+  if (status != SANE_STATUS_GOOD)
     {
-      DBG (DBG_error, "attach_scanner: open failed\n");
-      free (dev);
-      return SANE_STATUS_INVAL;
+      status = pie_usb_attach_open (devicename, &sfd, &model);
     }
-
-  if (bufsize < 4096)		/* < 4KB */
+  if (status != SANE_STATUS_GOOD)
     {
-      DBG (DBG_error,
-	   "attach_scanner: sanei_scsi_open_extended returned too small scsi buffer (%d)\n",
-	   bufsize);
-      sanei_scsi_close (sfd);
       free (dev);
-      return SANE_STATUS_NO_MEM;
+      return status;
     }
 
-  DBG (DBG_info,
-       "attach_scanner: sanei_scsi_open_extended returned scsi buffer size = %d\n",
-       bufsize);
-#else
-  bufsize = sanei_scsi_max_request_size;
-
-  if (sanei_scsi_open (devicename, &sfd, sense_handler, dev) != 0)
-    {
-      DBG (DBG_error, "attach_scanner: open failed\n");
-      free (dev);
-
-      return SANE_STATUS_INVAL;
+  pie_init (dev, model);		/* preset values in structure dev */
 
-    }
-#endif
+  DBG (DBG_info, "attach_scanner: model %d\n", model);
 
-  pie_init (dev);		/* preset values in structure dev */
 
   dev->devicename = strdup (devicename);
 
@@ -1178,12 +1015,18 @@ attach_scanner (const char *devicename, Pie_Device ** devp)
   dev->scan_mode_list[3] = HALFTONE_STR;
   dev->scan_mode_list[4] = 0;
 
-  sanei_scsi_close (sfd);
+  if (model == 0)
+    sanei_scsi_close (sfd);
+  else
+    sanei_usb_close (sfd);
 
   dev->sane.name = dev->devicename;
   dev->sane.vendor = dev->vendor;
   dev->sane.model = dev->product;
-  dev->sane.type = "flatbed scanner";
+  if (model == 0)
+    dev->sane.type = "flatbed scanner";
+  else
+    dev->sane.type = "film scanner";
 
   dev->x_range.min = SANE_FIX (0);
   dev->x_range.quant = SANE_FIX (0);
@@ -1228,6 +1071,10 @@ attach_scanner (const char *devicename, Pie_Device ** devp)
   return SANE_STATUS_GOOD;
 }
 
+/*   DBG (DBG_info, "attach_scanner: TODO forcefully aborted\n");
+  return SANE_STATUS_INVAL;		TODO forcefully aborted */
+
+
 /* --------------------------- MAX STRING SIZE ---------------------------- */
 
 
@@ -1497,7 +1344,7 @@ pie_power_save (Pie_Scanner * scanner, int time)
   data[4] = time & 0x7f;
 
   status =
-    sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
+    (*pie_scsi_cmd) (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error, "pie_power_save: write command returned status %s\n",
@@ -1537,7 +1384,7 @@ pie_send_exposure_one (Pie_Scanner * scanner, int filter, int value)
   set_data (data, 6, (int) value, 2);
 
   status =
-    sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
+    (*pie_scsi_cmd) (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error,
@@ -1604,7 +1451,7 @@ pie_send_highlight_shadow_one (Pie_Scanner * scanner, int filter,
   data[7] = shadow;
 
   status =
-    sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
+    (*pie_scsi_cmd) (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error,
@@ -1730,7 +1577,7 @@ pie_perform_cal (Pie_Scanner * scanner, int cal_index)
       DBG (DBG_info, "pie_perform_cal: reading 1 line (%lu bytes)\n", (u_long) size);
 
       status =
-	sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, rcv_buffer,
+	(*pie_scsi_cmd) (scanner->sfd, sread.cmd, sread.size, rcv_buffer,
 			&size);
 
       if (status)
@@ -1905,7 +1752,7 @@ pie_perform_cal (Pie_Scanner * scanner, int cal_index)
   DBG_DUMP (DBG_dump, send_buffer, 64);
 
   status =
-    sanei_scsi_cmd (scanner->sfd, send_buffer, swrite.size + size, NULL,
+    (*pie_scsi_cmd) (scanner->sfd, send_buffer, swrite.size + size, NULL,
 		    NULL);
   if (status)
     {
@@ -2010,7 +1857,7 @@ pie_dwnld_gamma_one (Pie_Scanner * scanner, int filter, SANE_Int * table)
   DBG_DUMP (DBG_dump, data, 128);
 
   status =
-    sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
+    (*pie_scsi_cmd) (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error,
@@ -2118,7 +1965,7 @@ pie_set_window (Pie_Scanner * scanner)
   DBG (DBG_info, "BR_Y: %d\n", (int) x);
 
   status =
-    sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
+    (*pie_scsi_cmd) (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error, "pie_set_window: write command returned status %s\n",
@@ -2289,7 +2136,7 @@ pie_mode_select (Pie_Scanner * scanner)
   DBG (DBG_info, "pie_mode_select: threshold %02x\n", data[13]);
 
   status =
-    sanei_scsi_cmd (scanner->sfd, buffer, smode.size + size, NULL, NULL);
+    (*pie_scsi_cmd) (scanner->sfd, buffer, smode.size + size, NULL, NULL);
   if (status)
     {
       DBG (DBG_error, "pie_mode_select: write command returned status %s\n",
@@ -2320,7 +2167,7 @@ pie_scan (Pie_Scanner * scanner, int start)
 
   do
     {
-      status = sanei_scsi_cmd (scanner->sfd, scan.cmd, scan.size, NULL, NULL);
+      status = (*pie_scsi_cmd) (scanner->sfd, scan.cmd, scan.size, NULL, NULL);
       if (status)
 	{
 	  DBG (DBG_error, "pie_scan: write command returned status %s\n",
@@ -2356,7 +2203,7 @@ pie_wait_scanner (Pie_Scanner * scanner)
 	}
       /* test unit ready */
       status =
-	sanei_scsi_cmd (scanner->sfd, test_unit_ready.cmd,
+	(*pie_scsi_cmd) (scanner->sfd, test_unit_ready.cmd,
 			test_unit_ready.size, NULL, NULL);
       cnt++;
 
@@ -2405,7 +2252,7 @@ pie_get_params (Pie_Scanner * scanner)
   set_param_length (param.cmd, size);
 
   status =
-    sanei_scsi_cmd (scanner->sfd, param.cmd, param.size, buffer, &size);
+    (*pie_scsi_cmd) (scanner->sfd, param.cmd, param.size, buffer, &size);
 
   if (status)
     {
@@ -2480,7 +2327,7 @@ pie_grab_scanner (Pie_Scanner * scanner)
     return status;
 
   status =
-    sanei_scsi_cmd (scanner->sfd, reserve_unit.cmd, reserve_unit.size, NULL,
+    (*pie_scsi_cmd) (scanner->sfd, reserve_unit.cmd, reserve_unit.size, NULL,
 		    NULL);
 
 
@@ -2509,7 +2356,7 @@ pie_give_scanner (Pie_Scanner * scanner)
   DBG (DBG_info2, "trying to release scanner ...\n");
 
   status =
-    sanei_scsi_cmd (scanner->sfd, release_unit.cmd, release_unit.size, NULL,
+    (*pie_scsi_cmd) (scanner->sfd, release_unit.cmd, release_unit.size, NULL,
 		    NULL);
   if (status)
     {
@@ -2595,7 +2442,7 @@ pie_reader_process_indexed (Pie_Scanner * scanner, FILE * fp)
       do
 	{
 	  status =
-	    sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, buffer,
+	    (*pie_scsi_cmd) (scanner->sfd, sread.cmd, sread.size, buffer,
 			    &size);
 	}
       while (status);
@@ -2736,7 +2583,7 @@ pie_reader_process (Pie_Scanner * scanner, FILE * fp)
       do
 	{
 	  status =
-	    sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, buffer,
+	    (*pie_scsi_cmd) (scanner->sfd, sread.cmd, sread.size, buffer,
 			    &size);
 	}
       while (status);
@@ -2858,7 +2705,7 @@ reader_process ( void *data )	/* executed as a child process */
 /* -------------------------------- ATTACH_ONE ---------------------------------- */
 
 
-/* callback function for sanei_config_attach_matching_devices(dev_name, attach_one) */
+/* callback function for sanei_usb_attach_matching_devices(dev_name, attach_one) */
 static SANE_Status
 attach_one (const char *name)
 {
@@ -2940,6 +2787,9 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize
   if (version_code)
     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
 
+  /* init usb use */
+  sanei_usb_init ();
+
   fp = sanei_config_open (PIE_CONFIG_FILE);
   if (!fp)
     {
@@ -2961,7 +2811,8 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize
 	  continue;
 	}
 
-      sanei_config_attach_matching_devices (dev_name, attach_one);
+      DBG (DBG_sane_proc, "sane_init() trying %s\n", dev_name);
+      sanei_config_attach_matching_devices (dev_name, try_attach_usb);
     }
 
   fclose (fp);
@@ -3413,6 +3264,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
 		/* scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; */
 		scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
 		scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
+
 		scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
 	      }
 	    return SANE_STATUS_GOOD;
diff --git a/backend/pie.conf.in b/backend/pie.conf.in
index b8a519b..517539b 100644
--- a/backend/pie.conf.in
+++ b/backend/pie.conf.in
@@ -1,4 +1,8 @@
 scsi DEVCOM * Scanner
 scsi PIE * Scanner
 scsi AdLib * Scanner
+
+# Reflecta ProScan 7200
+usb 0x05e3 0x0145
+
 /dev/scanner
diff --git a/backend/pie.h b/backend/pie.h
new file mode 100644
index 0000000..f374b03
--- /dev/null
+++ b/backend/pie.h
@@ -0,0 +1,301 @@
+/* sane - Scanner Access Now Easy.
+
+   pie.h
+
+   Copyright (C) 2000 Simon Munton, based on the umax backend by Oliver Rauch
+   Copyright (C) 2011 Michael Rickmann <mrickma@gwdg.de>
+                 for USB part
+   
+   This file is part of the SANE package.
+   
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+   
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+   
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+   
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+   
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+   
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice. 
+*/
+
+#ifndef PIE_DEFS_H
+#define PIE_DEFS_H
+
+/* --------------- defines moved here from pie.c --------------- */
+
+#define DBG_error0  0
+#define DBG_error   1
+#define DBG_sense   2
+#define DBG_warning 3
+#define DBG_inquiry 4
+
+#define DBG_info    5
+#define DBG_info2   6
+#define DBG_proc    7
+#define DBG_read    8
+#define DBG_sane_init   10
+#define DBG_sane_proc   11
+#define DBG_sane_info   12
+#define DBG_sane_option 13
+#define DBG_dump	14
+
+#define BUILD 10
+
+#define PIE_CONFIG_FILE "pie.conf"
+
+#define LINEART_STR         SANE_VALUE_SCAN_MODE_LINEART
+#define HALFTONE_STR        SANE_VALUE_SCAN_MODE_HALFTONE
+#define GRAY_STR            SANE_VALUE_SCAN_MODE_GRAY
+#define COLOR_STR           SANE_VALUE_SCAN_MODE_COLOR
+
+#define LINEART             1
+#define HALFTONE            2
+#define GRAYSCALE           3
+#define RGB                 4
+
+#define CAL_MODE_PREVIEW        (INQ_CAP_FAST_PREVIEW)
+#define CAL_MODE_FLATBED        0x00
+#define CAL_MODE_ADF            (INQ_OPT_DEV_ADF)
+#define CAL_MODE_TRANPSARENCY   (INQ_OPT_DEV_TP)
+#define CAL_MODE_TRANPSARENCY1  (INQ_OPT_DEV_TP1)
+
+#define min(a,b) (((a)<(b))?(a):(b))
+#define max(a,b) (((a)>(b))?(a):(b))
+
+/* times (in us) to delay after certain commands. Scanner seems to lock up if it returns busy
+ * status and commands are repeatedly reissued (by kernel error handler) */
+
+#define DOWNLOAD_GAMMA_WAIT_TIME	(1000000)
+#define SCAN_WAIT_TIME			(1000000)
+#define SCAN_WARMUP_WAIT_TIME		(500000)
+#define TUR_WAIT_TIME			(500000)
+
+
+/* options supported by the scanner */
+
+enum Pie_Option
+{
+  OPT_NUM_OPTS = 0,
+
+  /* ------------------------------------------- */
+  OPT_MODE_GROUP,
+  OPT_MODE,
+  OPT_RESOLUTION,
+
+
+  /* ------------------------------------------- */
+
+  OPT_GEOMETRY_GROUP,
+  OPT_TL_X,			/* top-left x */
+  OPT_TL_Y,			/* top-left y */
+  OPT_BR_X,			/* bottom-right x */
+  OPT_BR_Y,			/* bottom-right y */
+
+  /* ------------------------------------------- */
+
+  OPT_ENHANCEMENT_GROUP,
+
+  OPT_HALFTONE_PATTERN,
+  OPT_SPEED,
+  OPT_THRESHOLD,
+
+  OPT_GAMMA_VECTOR,
+  OPT_GAMMA_VECTOR_R,
+  OPT_GAMMA_VECTOR_G,
+  OPT_GAMMA_VECTOR_B,
+
+  /* ------------------------------------------- */
+
+  OPT_ADVANCED_GROUP,
+  OPT_PREVIEW,
+
+  /* must come last: */
+  NUM_OPTIONS
+};
+
+
+/* This defines the information needed during calibration */
+
+struct Pie_cal_info
+{
+  int cal_type;
+  int receive_bits;
+  int send_bits;
+  int num_lines;
+  int pixels_per_line;
+};
+
+
+/* This structure holds the information about a physical scanner */
+
+typedef struct Pie_Device
+{
+  struct Pie_Device *next;
+
+  char *devicename;		/* name of the scanner device */
+
+  char vendor[9];		/* will be xxxxx */
+  char product[17];		/* e.g. "SuperVista_S12" or so */
+  char version[5];		/* e.g. V1.3 */
+
+  SANE_Int model;		/* currently 0 for SCSI, > 0 for USB scanners */
+  SANE_Device sane;
+  SANE_Range dpi_range;
+  SANE_Range x_range;
+  SANE_Range y_range;
+
+  SANE_Range exposure_range;
+  SANE_Range shadow_range;
+  SANE_Range highlight_range;
+
+  int inquiry_len;		/* length of inquiry return block */
+
+  int inquiry_x_res;		/* maximum x-resolution */
+  int inquiry_y_res;		/* maximum y-resolution */
+  int inquiry_pixel_resolution;
+  double inquiry_fb_width;	/* flatbed width in inches */
+  double inquiry_fb_length;	/* flatbed length in inches */
+
+  int inquiry_trans_top_left_x;
+  int inquiry_trans_top_left_y;
+  double inquiry_trans_width;	/* transparency width in inches */
+  double inquiry_trans_length;	/* transparency length in inches */
+
+  int inquiry_halftones;	/* number of halftones supported */
+  int inquiry_filters;		/* available colour filters */
+  int inquiry_color_depths;	/* available colour depths */
+  int inquiry_color_format;	/* colour format from scanner */
+  int inquiry_image_format;	/* image data format */
+  int inquiry_scan_capability;	/* additional scanner features, number of speeds */
+  int inquiry_optional_devices;	/* optional devices */
+  int inquiry_enhancements;	/* enhancements */
+  int inquiry_gamma_bits;	/* no of bits used for gamma table */
+  int inquiry_fast_preview_res;	/* fast preview resolution */
+  int inquiry_min_highlight;	/* min highlight % that can be used */
+  int inquiry_max_shadow;	/* max shadow % that can be used */
+  int inquiry_cal_eqn;		/* which calibration equation to use */
+  int inquiry_min_exp;		/* min exposure % */
+  int inquiry_max_exp;		/* max exposure % */
+
+  SANE_String scan_mode_list[7];	/* holds names of types of scan (color, ...) */
+
+  SANE_String halftone_list[17];	/* holds the names of the halftone patterns from the scanner */
+
+  SANE_String speed_list[9];	/* holds the names of available speeds */
+
+  int cal_info_count;		/* number of calibration info sets */
+  struct Pie_cal_info *cal_info;	/* points to the actual calibration information */
+}
+Pie_Device;
+
+/* This structure holds information about an instance of an 'opened' scanner */
+
+typedef struct Pie_Scanner
+{
+  struct Pie_Scanner *next;
+  Pie_Device *device;		/* pointer to physical scanner */
+
+  int sfd;			/* scanner file desc. */
+  int bufsize;			/* max scsi buffer size */
+
+  SANE_Option_Descriptor opt[NUM_OPTIONS];	/* option descriptions for this instance */
+  Option_Value val[NUM_OPTIONS];	/* option settings for this instance */
+  SANE_Int *gamma_table[4];	/* gamma tables for this instance */
+  SANE_Range gamma_range;
+  int gamma_length;		/* size of gamma table */
+
+  int scanning;			/* true if actually doing a scan */
+  SANE_Parameters params;
+
+  SANE_Pid reader_pid;
+  int pipe;
+  int reader_fds;
+  
+  int colormode;		/* whether RGB, GRAY, LINEART, HALFTONE */
+  int resolution;
+  int cal_mode;			/* set to value to compare cal_info mode to */
+
+  int cal_filter;		/* set to indicate which filters will provide data for cal */
+
+  int filter_offset1;		/* offsets between colors in indexed scan mode */
+  int filter_offset2;
+
+  int bytes_per_line;		/* number of bytes per line */
+
+}
+Pie_Scanner;
+
+
+/* --------------- defines for the USB code --------------- */
+
+
+#define BULKIN_MAXSIZE          0xFFF0
+
+/* USB control message values */
+
+#define REQUEST_TYPE_IN		(USB_TYPE_VENDOR | USB_DIR_IN)
+#define REQUEST_TYPE_OUT	(USB_TYPE_VENDOR | USB_DIR_OUT)
+
+#define REQUEST_REGISTER	0x0c
+#define REQUEST_BUFFER		0x04
+
+#define VALUE_BUFFER		0x82
+#define VALUE_READ_REGISTER	0x84
+#define VALUE_WRITE_REGISTER	0x85
+#define VALUE_INIT_1		0x87
+#define VALUE_INIT_2		0x88
+
+#define INDEX			0x00
+
+/* e.g.
+   control  0x40 0x0c 0x87 0x00 len     1 wrote 0x04
+            REQUEST_TYPE_OUT
+                 REQUEST_REGISTER
+                      VALUE_INIT_1
+                           INDEX
+*/
+
+
+typedef struct PIE_USB_Value_Data
+{
+  SANE_Byte bValue;
+  SANE_Byte bData;
+} PIE_USB_Value_Data;
+
+
+typedef struct PIE_USB_Device_Entry
+{
+  SANE_Word vendor;			/* USB vendor identifier */
+  SANE_Word product;			/* USB product identifier */
+  SANE_Word model;			/* currently only count >= 1 */
+} PIE_USB_Device_Entry;
+
+
+#endif /* not PIE_DEFS_H */
diff --git a/backend/pie_usb.c b/backend/pie_usb.c
new file mode 100644
index 0000000..aab3e72
--- /dev/null
+++ b/backend/pie_usb.c
@@ -0,0 +1,459 @@
+/* sane - Scanner Access Now Easy.
+
+   pie-usb.c
+
+   Copyright (C) 2011 Michael Rickmann <mrickma@gwdg.de>
+   
+   This file is part of the SANE package.
+   
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+   
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+   
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+   
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+   
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+   
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice. 
+*/
+
+
+/* list of USB descriptors */
+
+static PIE_USB_Device_Entry pie_usb_device_list[] = {
+  {0x05e3, 0x0145, 1},			/* Reflecta ProScan 7200	*/
+					/* Reflecta CrystalScan 7200	*/
+  {0, 0, 0}
+};
+
+/* values for some stereotype USB control write sequences */
+
+static PIE_USB_Value_Data PIE_USB_Init_Sequence_1[] = {
+  {VALUE_INIT_1, 0x04},
+  {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0xaa}, {VALUE_INIT_2, 0x55}, {VALUE_INIT_2, 0x00},
+  {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0x87}, {VALUE_INIT_2, 0x78}, {VALUE_INIT_2, 0x30},
+  {VALUE_INIT_1, 0x05}, {VALUE_INIT_1, 0x04},
+  {VALUE_INIT_2, 0xff},
+  {0x0, 0x0}
+};
+
+static PIE_USB_Value_Data PIE_USB_Init_Sequence_2[] = {
+  {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0xaa}, {VALUE_INIT_2, 0x55}, {VALUE_INIT_2, 0x00},
+  {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0x87}, {VALUE_INIT_2, 0x78}, {VALUE_INIT_2, 0x00},
+  {VALUE_INIT_1, 0x05}, {VALUE_INIT_1, 0x04},
+  {VALUE_INIT_2, 0xff},
+  {0x0, 0x0}
+};
+
+static PIE_USB_Value_Data PIE_USB_Setup_SCSI_Sequence[] = {
+  {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0xaa}, {VALUE_INIT_2, 0x55}, {VALUE_INIT_2, 0x00},
+  {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0x87}, {VALUE_INIT_2, 0x78}, {VALUE_INIT_2, 0xe0},
+  {VALUE_INIT_1, 0x05}, {VALUE_INIT_1, 0x04},
+  {VALUE_INIT_2, 0xff},
+  {0x0, 0x0}
+};
+
+
+/* forward / prototype declarations */
+
+static SANE_Status attach_one (const char *name);
+SANE_Status pie_usb_scsi_wrapper (int fd, const void * src, size_t src_size,
+                                          void * dst, size_t * dst_size);
+
+
+
+SANE_Status (*pie_scsi_cmd) (int fd, const void * src, size_t src_size, void * dst, size_t * dst_size);
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ low level USB ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* ----------------------- PIE_USB_WRITE_CONTROL_SEQUENCE ------------------------ */
+
+static SANE_Status
+pie_usb_write_control_sequence (SANE_Int dn, PIE_USB_Value_Data sequ[])
+{
+  SANE_Int status = SANE_STATUS_GOOD;
+  int i;
+
+  DBG (DBG_info, "pie_usb_write_control_sequence writing\n");
+
+  for (i = 0; (status == SANE_STATUS_GOOD) && (sequ[i].bValue != 0); i++)
+  {
+    status =
+      sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
+                             sequ[i].bValue, INDEX, 1, &(sequ[i].bData));
+    if (status != SANE_STATUS_GOOD)
+    {
+      DBG (DBG_error, "pie_usb_write_control_sequence failed\n");
+      return status;
+    }
+  }
+  return SANE_STATUS_GOOD;
+}
+
+/* ---------------------------- PIE_USB_READY_STATE ------------------------------ */
+
+/* Actually, there are two answers, a simple one where 1 byte with 0 or 1 is ok,   */
+/* and a more elaborate one in two bytes starting with 3. The second byte signals  */
+/* some condition, 0 is ready.                                                     */
+
+static SANE_Status
+pie_usb_ready_state (SANE_Int dn, SANE_Int * state)
+{
+  SANE_Status status;
+  SANE_Byte val;
+
+  status =
+    sanei_usb_control_msg (dn, REQUEST_TYPE_IN, REQUEST_REGISTER,
+			   VALUE_READ_REGISTER, INDEX, 1, &val);
+  if (status != SANE_STATUS_GOOD)
+  {
+    DBG (DBG_error, "pie_usb_ready_state failed at 1st read\n");
+    return status;
+  }
+
+  DBG (DBG_info, "pie_usb_ready_state got 0x%02x at 1st read\n", val);
+  if (val <= 1)
+  {
+    *state = 0;
+    return SANE_STATUS_GOOD;
+  }
+  if (val != 3)
+  {
+    DBG (DBG_error, "pie_usb_ready_state failed\n");
+    return SANE_STATUS_INVAL;
+  }
+
+  status =
+    sanei_usb_control_msg (dn, REQUEST_TYPE_IN, REQUEST_REGISTER,
+			   VALUE_READ_REGISTER, INDEX, 1, &val);
+  if (status != SANE_STATUS_GOOD)
+  {
+    DBG (DBG_error, "pie_usb_ready_state failed at 2nd read\n");
+    return status;
+  }
+
+  DBG (DBG_info, "pie_usb_ready_state got 0x%02x at 2nd read\n", val);
+  *state = val;
+
+  return SANE_STATUS_GOOD;
+}
+
+
+/* --------------------------- PIE_USB_WRITE_SCSI_CMD ---------------------------- */
+
+static SANE_Status
+pie_usb_write_scsi_cmd (SANE_Int dn, const SANE_Byte cmnd[6])
+{
+  SANE_Status status;
+  SANE_Byte mnd;
+  int i;
+
+  DBG (DBG_info, "pie_usb_write_scsi_cmd writing 6 bytes\n");
+
+  for (i = 0; i < 6; i++)
+  {
+    mnd = cmnd[i];
+    status =
+      sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
+                             VALUE_WRITE_REGISTER, INDEX, 1, &mnd);
+    if (status != SANE_STATUS_GOOD)
+    {
+      DBG (DBG_error, "pie_usb_write_scsi_cmd failed at byte %d\n", i);
+      return status;
+    }
+  }
+  return SANE_STATUS_GOOD;
+}
+
+
+/* ----------------------------- PIE_USB_BULK_READ ------------------------------- */
+
+static SANE_Status
+pie_usb_bulk_read (SANE_Int dn, SANE_Byte * data, size_t len)
+{
+  SANE_Status status;
+  size_t size;
+  SANE_Byte outdata[8];
+
+  DBG (DBG_info, "pie_usb_bulk_read requesting %lu bytes\n",
+       (u_long) len);
+
+  if (len == 0)
+
+      return SANE_STATUS_GOOD;
+
+  memset (outdata, '\0', sizeof(outdata));
+
+  while (len)
+  {
+    if (len > BULKIN_MAXSIZE)
+      size = BULKIN_MAXSIZE;
+    else
+      size = len;
+
+    outdata[4] = (size & 0xff);
+    outdata[5] = ((size >> 8) & 0xff);
+    outdata[6] = ((size >> 16) & 0xff);
+    outdata[7] = ((size >> 24) & 0xff);
+
+    status =
+      sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
+                             VALUE_BUFFER, INDEX, sizeof (outdata), outdata);
+    if (status != SANE_STATUS_GOOD)
+    {
+      DBG (DBG_error,
+           "pie_usb_bulk_read failed while writing command: %s\n",
+           sane_strstatus (status));
+      return status;
+    }
+
+    DBG (DBG_info,
+         "pie_usb_bulk_read trying to read %lu bytes of data\n",
+         (u_long) size);
+    status = sanei_usb_read_bulk (dn, data, &size);
+    if (status != SANE_STATUS_GOOD)
+    {
+      DBG (DBG_error,
+           "pie_usb_bulk_read failed while reading bulk data: %s\n",
+           sane_strstatus (status));
+      return status;
+    }
+
+    DBG (DBG_info,
+         "pie_usb_bulk_read read %lu bytes, %lu remaining\n",
+         (u_long) size, (u_long) (len - size));
+    len -= size;
+    data += size;
+  }
+
+  DBG (DBG_info, "pie_usb_bulk_read completed\n");
+  return SANE_STATUS_GOOD;
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SCSI over USB ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* ------------------------------- PIE_USB_READ ---------------------------------- */
+
+/* note: the transfer length in a real 6-byte READ command can have two meanings:  */
+/* Normally it means length in bytes, however, when an image is read it amounts to */
+/* (lines * color-planes)                                                          */
+
+static SANE_Status
+pie_usb_READ (int dn, const SANE_Byte * cmnd, void * buf, size_t * buf_len)
+{
+  SANE_Int busy_state = 0;
+  SANE_Status status;
+  size_t length = *buf_len;
+
+  status = pie_usb_write_scsi_cmd (dn, cmnd);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+  status = pie_usb_ready_state (dn, &busy_state);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+  if (busy_state != 0)
+    return busy_state;
+
+  status = pie_usb_bulk_read (dn, buf, length);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+  status = pie_usb_ready_state (dn, &busy_state);
+  if (busy_state != 0)
+    return busy_state;
+
+  return status;
+}
+
+/* ------------------------------- PIE_USB_WRITE --------------------------------- */
+
+static SANE_Status
+pie_usb_WRITE (int dn, const SANE_Byte * cmnd, size_t length)
+{
+  SANE_Int busy_state = 0;
+  SANE_Status status;
+  SANE_Byte mnd;
+  size_t i;
+
+  DBG (DBG_info, "pie_usb_WRITE\n");
+  if (length <= 6)
+    return SANE_STATUS_GOOD;
+
+  status = pie_usb_write_scsi_cmd (dn, cmnd);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+  status = pie_usb_ready_state (dn, &busy_state);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+  if (busy_state != 0)
+    return busy_state;
+
+  DBG (DBG_info,"pie_usb_WRITE: now writing %lu bytes\n",
+       (u_long) length - 6);
+  for (i = 6; i < length; i++)
+  {
+    mnd = cmnd[i];
+    status =
+      sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
+                             VALUE_WRITE_REGISTER, INDEX, 1, &mnd);
+    if (status != SANE_STATUS_GOOD)
+    {
+      DBG (DBG_error, "pie_usb_WRITE failed at byte %lu\n",
+           (unsigned long) length);
+      return status;
+    }
+  }
+  status = pie_usb_ready_state (dn, &busy_state);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+  if (busy_state != 0)
+    return busy_state;
+
+  return SANE_STATUS_GOOD;
+}
+
+/* ------------------------------ PIE_USB_INQUIRY -------------------------------- */
+
+
+
+/* ---------------------------- PIE_USB_SCSI_WRAPPER ----------------------------- */
+
+/* Entry for SCSI over USB command wrapping                                        */
+
+SANE_Status
+pie_usb_scsi_wrapper (int fd, const void * src, size_t src_size, void * dst, size_t * dst_size)
+{
+  SANE_Status status = SANE_STATUS_GOOD;
+  const SANE_Byte *cmnd = src;
+
+  if (cmnd[0] == INQUIRY)
+  {
+    status = pie_usb_write_control_sequence (fd, PIE_USB_Init_Sequence_1);
+    if (status != SANE_STATUS_GOOD)
+      return status;
+    status = pie_usb_write_control_sequence (fd, PIE_USB_Init_Sequence_2);
+    if (status != SANE_STATUS_GOOD)
+      return status;
+  }
+  status = pie_usb_write_control_sequence (fd, PIE_USB_Setup_SCSI_Sequence);
+  if (status != SANE_STATUS_GOOD)
+    return status;
+
+  switch (cmnd[0])
+  {
+    case READ:
+      DBG (DBG_info, "pie_usb_scsi_wrapper doing READ\n");
+      pie_usb_READ (fd, cmnd, dst, dst_size);
+      break;
+    case WRITE:
+      DBG (DBG_info, "pie_usb_scsi_wrapper doing WRITE\n");
+      pie_usb_WRITE (fd, cmnd, src_size);
+      break;
+    case INQUIRY:
+      DBG (DBG_info, "pie_usb_scsi_wrapper doing INQUIRY\n");
+      status = pie_usb_READ (fd, cmnd, dst, dst_size);
+      break;
+
+    default:
+      DBG (DBG_info, "pie_usb_scsi_wrapper called for command %d\n", cmnd[0]);
+      break;
+  }
+
+
+  return status;
+}
+
+
+/* ----------------------------- PIE_USB_ATTACH_OPEN ----------------------------- */
+
+/* called during initialization, tries to open and identify an USB scanner	   */
+
+static SANE_Status
+pie_usb_attach_open (SANE_String_Const devname, SANE_Int * dn, SANE_Int * model)
+{
+  SANE_Status status;
+  SANE_Int vendor, product;
+  int i;
+
+  DBG (DBG_info, "pie_usb_attach_open: opening `%s'\n", devname);
+  status = sanei_usb_open (devname, dn);
+  if (status != SANE_STATUS_GOOD)
+  {
+    DBG (DBG_error, "pie_usb_attach_open: sanei_usb_open failed\n");
+    return status;
+  }
+  DBG (DBG_info, "pie_usb_attach_open: USB device `%s' successfully opened\n",
+       devname);
+
+  status = sanei_usb_get_vendor_product (*dn, &vendor, &product);
+  if (status != SANE_STATUS_GOOD)
+  {
+    DBG (DBG_error,
+         "pie_usb_attach_open: couldn't get vendor and product ids of device `%s': %s\n",
+         devname, sane_strstatus (status));
+    return status;
+  }
+
+  *model = 0;
+  for (i = 0; pie_usb_device_list[i].model != 0; i++)
+  {
+    if (vendor == pie_usb_device_list[i].vendor &&
+        product == pie_usb_device_list[i].product)
+    {
+      *model = pie_usb_device_list[i].model;
+      break;
+    }
+  }
+  if (model == 0)
+  {
+    DBG (DBG_error,
+         "pie_usb_attach_open: vendor 0x%04x product 0x%04x is not supported by this backend\n",
+         vendor, product);
+    status = SANE_STATUS_INVAL;
+  }
+
+  return status;
+}
+
+
+/* -------------------------------- TRY_ATTACH_USB ------------------------------- */
+
+/* callback function for sanei_config_attach_matching_devices which has checked    */
+/* for SCSI scanners. Here we do it for USB ones                                   */
+
+static SANE_Status
+try_attach_usb (const char *name)
+{
+  sanei_usb_attach_matching_devices (name, attach_one);
+  return SANE_STATUS_GOOD;
+}
+
+
+
diff --git a/doc/descriptions/pie.desc b/doc/descriptions/pie.desc
index 45abb8e..70e800d 100644
--- a/doc/descriptions/pie.desc
+++ b/doc/descriptions/pie.desc
@@ -94,5 +94,16 @@
 :interface "SCSI"
 :status :untested
 
+; -----------------------------------------------------------------------------
+
+:mfg "reflecta"
+:url "https://reflecta.de/"
+
+:model "Reflecta ProScan 7200"
+:interface "USB"
+:usbid "0x05e3" "0x0145"
+:status :basic
+:comment "Similar to PrimeFilm 7250 scanners from Pacific Image Electronics"
+
 ; :comment and :url specifiers are optional after :mfg, :model, :desc,
 ;  and at the top-level.
