kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			950 wiersze
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			950 wiersze
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
| #include "../../include/sane/config.h"
 | |
| 
 | |
| #include <errno.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| #include <math.h>
 | |
| #include <stddef.h>
 | |
| #ifdef HAVE_SYS_TIME_H
 | |
| #include <sys/time.h>
 | |
| #endif
 | |
| #ifdef HAVE_SYS_TYPES_H
 | |
| #include <sys/types.h>
 | |
| #endif
 | |
| #ifdef HAVE_MKDIR
 | |
| #include <sys/stat.h>
 | |
| #include <sys/types.h>
 | |
| #endif
 | |
| 
 | |
| #include <assert.h>
 | |
| 
 | |
| #define BACKEND_NAME	sanei_usb
 | |
| 
 | |
| #include "../../include/sane/sane.h"
 | |
| #include "../../include/sane/sanei.h"
 | |
| #include "../../include/sane/saneopts.h"
 | |
| 
 | |
| #include "../../include/sane/sanei_backend.h"
 | |
| #include "../../include/sane/sanei_usb.h"
 | |
| 
 | |
| #include "../../include/_stdint.h"
 | |
| 
 | |
| /*
 | |
|  * In order to avoid modifying sanei_usb.c to allow for unit tests
 | |
|  * we include it so we can use its private variables and structures
 | |
|  * and still test the code.
 | |
|  */
 | |
| #include "../../sanei/sanei_usb.c"
 | |
| 
 | |
| 
 | |
| /** test sanei_usb_init()
 | |
|  * calls sanei_usb_init
 | |
|  * @param expected expected use count
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_init (int expected)
 | |
| {
 | |
|   /* initialize USB */
 | |
|   printf ("%s starting ...\n", __func__);
 | |
|   sanei_usb_init ();
 | |
|   if (initialized == 0)
 | |
|     {
 | |
|       printf ("ERROR: sanei_usb not initialized!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   if (initialized != expected)
 | |
|     {
 | |
|       printf ("ERROR: incorrect use count, expected %d, got %d!\n", expected,
 | |
| 	      initialized);
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   printf ("sanei_usb initialized, use count is %d ...\n", initialized);
 | |
|   printf ("%s success\n\n", __func__);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** test sanei_usb_exit()
 | |
|  * calls sanei_usb_exit
 | |
|  * @param expected use count after exit call
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_exit (int expected)
 | |
| {
 | |
|   printf ("%s starting ...\n", __func__);
 | |
| 
 | |
|   /* end of USB use test */
 | |
|   sanei_usb_exit ();
 | |
|   if (initialized != expected)
 | |
|     {
 | |
|       printf ("ERROR: incorrect use count, expected %d, got %d!\n", expected,
 | |
| 	      initialized);
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   printf ("%s success\n\n", __func__);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| /** count detected devices
 | |
|  * count all detected devices and check it against expected value
 | |
|  * @param expected detected count
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| count_detected (int expected)
 | |
| {
 | |
|   int num = 0;
 | |
|   int i;
 | |
| 
 | |
|   for (i = 0; i < device_number; i++)
 | |
|     {
 | |
|       if (devices[i].missing == 0 && devices[i].devname != NULL)
 | |
| 	{
 | |
| 	  num++;
 | |
| 	}
 | |
|     }
 | |
|   if (num != expected)
 | |
|     {
 | |
|       printf ("ERROR: %d detected devices, expected %d!\n", num, expected);
 | |
|       return 0;
 | |
|     }
 | |
|   printf ("%d devices still detected.\n", num);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** create mock device
 | |
|  * create a mock device entry
 | |
|  * @param device device pointer to fill with mock data
 | |
|  * @return nothing
 | |
|  */
 | |
| static void
 | |
| create_mock_device (char *devname, device_list_type * device)
 | |
| {
 | |
|   memset (device, 0, sizeof (device_list_type));
 | |
|   device->devname = strdup (devname);
 | |
|   device->vendor = 0xdead;
 | |
|   device->product = 0xbeef;
 | |
| #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB)
 | |
|   device->method = sanei_usb_method_libusb;
 | |
| #endif
 | |
| #ifdef HAVE_USBCALLS
 | |
|   device->method = sanei_usb_method_usbcalls;
 | |
| #endif
 | |
| #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USBCALLS)
 | |
|   device->method == sanei_usb_method_scanner_driver;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /** test store_device
 | |
|  * test store_device for corner cases not covered by the
 | |
|  * other regular use by sanei_usb_scan_devices
 | |
|  * the startiing situation is that the mock device has never
 | |
|  * put into device list.
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_store_device (void)
 | |
| {
 | |
|   int current_number;
 | |
|   int expected;
 | |
|   int i;
 | |
|   int found;
 | |
|   device_list_type mock;
 | |
| 
 | |
|   create_mock_device ("mock", &mock);
 | |
| 
 | |
|   /* first test store when there is no more room
 | |
|    * to store device */
 | |
|   current_number = device_number;
 | |
|   device_number = MAX_DEVICES;
 | |
|   /* give unused devices a name so strcmp() won't crash. */
 | |
|   for (i = current_number; i < MAX_DEVICES; i++)
 | |
|     devices[i].devname = "";
 | |
| 
 | |
|   store_device (mock);
 | |
|   /* there should be no more devices */
 | |
|   if (device_number > MAX_DEVICES)
 | |
|     {
 | |
|       printf ("ERROR: store past end of device list!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   /* walk device list to be sure mock device hasn't been stored */
 | |
|   for (i = 0; i < MAX_DEVICES; i++)
 | |
|     {
 | |
|       if (devices[i].devname && !strcmp (devices[i].devname, mock.devname))
 | |
| 	{
 | |
| 	  printf
 | |
| 	    ("ERROR: device stored although there were no place for it!\n");
 | |
| 	  return 0;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* restore device_number */
 | |
|   device_number = current_number;
 | |
|   /* reset unused devnames to NULL */
 | |
|   for (i = current_number; i < MAX_DEVICES; i++)
 | |
|     devices[i].devname = NULL;
 | |
|   expected = device_number + 1;
 | |
| 
 | |
|   /* store mock device */
 | |
|   store_device (mock);
 | |
|   found = 0;
 | |
|   for (i = 0; i < MAX_DEVICES && !found; i++)
 | |
|     {
 | |
|       if (devices[i].devname && !strcmp (devices[i].devname, mock.devname))
 | |
| 	{
 | |
| 	  found = 1;
 | |
| 	}
 | |
|     }
 | |
|   if (device_number != expected || !found)
 | |
|     {
 | |
|       printf ("ERROR: mock device not stored !\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* scan devices should mark it as missing, and device_number should decrease */
 | |
|   sanei_usb_scan_devices ();
 | |
|   found = 0;
 | |
|   for (i = 0; i < MAX_DEVICES && !found; i++)
 | |
|     {
 | |
|       if (devices[i].devname
 | |
| 	  && devices[i].missing == 1
 | |
| 	  && !strcmp (devices[i].devname, mock.devname))
 | |
| 	{
 | |
| 	  found = 1;
 | |
| 	}
 | |
|     }
 | |
|   if (device_number != expected || !found)
 | |
|     {
 | |
|       printf ("ERROR: mock device still present !\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* second scan devices should mark missing to 2 */
 | |
|   sanei_usb_scan_devices ();
 | |
|   found = 0;
 | |
|   for (i = 0; i < MAX_DEVICES && !found; i++)
 | |
|     {
 | |
|       if (devices[i].devname
 | |
| 	  && devices[i].missing == 2
 | |
| 	  && !strcmp (devices[i].devname, mock.devname))
 | |
| 	{
 | |
| 	  found = 1;
 | |
| 	}
 | |
|     }
 | |
|   if (device_number != expected || !found)
 | |
|     {
 | |
|       printf ("ERROR: mock device slot not reusable !\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* store mock device again, slot in devices should be reused
 | |
|    * and device_number shouldn't change */
 | |
|   create_mock_device ("mock2", &mock);
 | |
|   store_device (mock);
 | |
|   found = 0;
 | |
|   for (i = 0; i < MAX_DEVICES && !found; i++)
 | |
|     {
 | |
|       if (devices[i].devname && !strcmp (devices[i].devname, mock.devname))
 | |
| 	{
 | |
| 	  found = 1;
 | |
| 	}
 | |
|     }
 | |
|   if (device_number != expected || !found)
 | |
|     {
 | |
|       printf ("ERROR: mock device not stored !\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* last rescan to wipe mock device out */
 | |
|   sanei_usb_scan_devices ();
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** return count of opened devices
 | |
|  * @return count of opened devices
 | |
|  */
 | |
| static int
 | |
| get_opened (void)
 | |
| {
 | |
|   int num = 0;
 | |
|   int i;
 | |
| 
 | |
|   for (i = 0; i < device_number; i++)
 | |
|     {
 | |
|       if (devices[i].missing == 0 && devices[i].devname != NULL
 | |
| 	  && devices[i].open == SANE_TRUE)
 | |
| 	{
 | |
| 	  num++;
 | |
| 	}
 | |
|     }
 | |
|   return num;
 | |
| }
 | |
| 
 | |
| /** count opened devices
 | |
|  * count all opended devices and check it against expected value
 | |
|  * @param expected use opened count
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| count_opened (int expected)
 | |
| {
 | |
|   int num = get_opened();
 | |
| 
 | |
|   if (num != expected)
 | |
|     {
 | |
|       printf ("ERROR: %d opened devices, expected %d!\n", num, expected);
 | |
|       return 0;
 | |
|     }
 | |
|   printf ("%d devices still opened.\n", num);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** open all devices
 | |
|  * loop on all existing devices and open them
 | |
|  * @param dn array to store opened device number
 | |
|  * @param expected number of devices to be opened
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_open_all (SANE_Int * dn, int expected)
 | |
| {
 | |
|   int opened = 0;
 | |
|   int i;
 | |
|   int last;
 | |
|   SANE_Status status;
 | |
| 
 | |
|   /* loop on detected devices and open them */
 | |
|   last = -1;
 | |
|   for (i = 0; i < device_number; i++)
 | |
|     {
 | |
|       if (devices[i].missing == 0 && devices[i].devname != NULL)
 | |
| 	{
 | |
| 	  /* open device */
 | |
| 	  status = sanei_usb_open (devices[i].devname, dn + opened);
 | |
| 	  if (status == SANE_STATUS_GOOD)
 | |
| 	    {
 | |
| 	      opened++;
 | |
| 	      last = i;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
|               if (status == SANE_STATUS_ACCESS_DENIED ||
 | |
|                   status == SANE_STATUS_DEVICE_BUSY)
 | |
|                 {
 | |
|                   expected--;
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
| 	          printf ("ERROR: couldn't open device %s!\n",
 | |
|                           devices[i].devname);
 | |
| 	          return 0;
 | |
|                 }
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|   printf ("opened %d devices\n", opened);
 | |
| 
 | |
|   /* try to reopen an opened device when there is one */
 | |
|   if (last >= 0)
 | |
|     {
 | |
|       status = sanei_usb_open (devices[last].devname, dn + opened);
 | |
|       if (status == SANE_STATUS_GOOD)
 | |
| 	{
 | |
| 	  printf ("ERROR: unexpected success when opening %s twice!\n",
 | |
| 		  devices[last].devname);
 | |
| 	  return 0;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* there should be as many opened devices than detected devices */
 | |
|   return count_opened (expected);
 | |
| }
 | |
| 
 | |
| /** test opening invalid device
 | |
|  * try to open an non existing device
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_open_invalid (void)
 | |
| {
 | |
|   SANE_Status status;
 | |
|   SANE_Int dn;
 | |
| 
 | |
|   status = sanei_usb_open ("invalid device", &dn);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: unexpected success opening invalid device!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** close all devices
 | |
|  * loop on all opened devices and close them
 | |
|  * @param dn array of opened device number
 | |
|  * @param expected number of devices to be closed
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_close_all (SANE_Int * dn, int expected)
 | |
| {
 | |
|   int closed = 0;
 | |
|   int i;
 | |
| 
 | |
|   /* loop on detected devices and open them */
 | |
|   for (i = 0; i < expected; i++)
 | |
|     {
 | |
|       /* close device */
 | |
|       sanei_usb_close (dn[i]);
 | |
|       closed++;
 | |
|     }
 | |
|   printf ("closed %d devices\n", closed);
 | |
| 
 | |
|   /* there should be any more opened devices */
 | |
|   return count_opened (0);
 | |
| }
 | |
| 
 | |
| 
 | |
| /** claim all open devices
 | |
|  * loop on all opened devices and claim interface 0
 | |
|  * @param dn array of opened device number
 | |
|  * @param expected number of devices to be claimed
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_claim_all (SANE_Int * dn, int expected)
 | |
| {
 | |
|   int claimed = 0;
 | |
|   int i;
 | |
|   SANE_Status status;
 | |
|   device_list_type mock;
 | |
| 
 | |
|   claimed = 0;
 | |
|   for (i = 0; i < expected; i++)
 | |
|     {
 | |
|       status = sanei_usb_claim_interface (dn[i], devices[dn[i]].interface_nr);
 | |
|       if (status != SANE_STATUS_GOOD)
 | |
| 	{
 | |
| 	  printf ("ERROR: couldn't claim interface 0 on device %d!\n", dn[i]);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  claimed++;
 | |
| 	}
 | |
|     }
 | |
|   if (claimed != expected)
 | |
|     {
 | |
|       printf ("ERROR: expected %d claimed interfaces, got %d!\n", expected,
 | |
| 	      claimed);
 | |
|       return 0;
 | |
|     }
 | |
|   printf ("%d devices claimed...\n\n", claimed);
 | |
| 
 | |
|   /* try to claim invalid device entry */
 | |
|   status = sanei_usb_claim_interface (device_number, 0);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: could claim interface 0 on invalid device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* create a mock device and make it missing by rescanning */
 | |
|   create_mock_device ("mock", &mock);
 | |
|   store_device (mock);
 | |
|   sanei_usb_scan_devices ();
 | |
| 
 | |
|   /* try to claim interface on missing device */
 | |
|   status = sanei_usb_claim_interface (device_number - 1, 0);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: could claim interface 0 on invalid device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* remove mock device */
 | |
|   device_number--;
 | |
|   free (devices[device_number].devname);
 | |
|   devices[device_number].devname = NULL;
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| /** release all claimed devices
 | |
|  * loop on all opened devices and claim interface 0
 | |
|  * @param dn array of opened device number
 | |
|  * @param expected number of devices to be claimed
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_release_all (SANE_Int * dn, int expected)
 | |
| {
 | |
|   int released = 0;
 | |
|   int i;
 | |
|   SANE_Status status;
 | |
|   device_list_type mock;
 | |
| 
 | |
|   released = 0;
 | |
|   for (i = 0; i < expected; i++)
 | |
|     {
 | |
|       status =
 | |
| 	sanei_usb_release_interface (dn[i], devices[dn[i]].interface_nr);
 | |
|       if (status != SANE_STATUS_GOOD)
 | |
| 	{
 | |
| 	  printf ("ERROR: couldn't release interface 0 on device %d!\n",
 | |
| 		  dn[i]);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  released++;
 | |
| 	}
 | |
|     }
 | |
|   if (released != expected)
 | |
|     {
 | |
|       printf ("ERROR: expected %d released interfaces, got %d!\n", expected,
 | |
| 	      released);
 | |
|       return 0;
 | |
|     }
 | |
|   printf ("%d devices released...\n\n", released);
 | |
| 
 | |
|   /* try to release invalid device entry */
 | |
|   status = sanei_usb_release_interface (device_number, 0);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: could release interface 0 on invalid device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* create a mock device and make it missing by rescanning */
 | |
|   create_mock_device ("mock", &mock);
 | |
|   store_device (mock);
 | |
|   sanei_usb_scan_devices ();
 | |
| 
 | |
|   /* try to claim interface on missing device */
 | |
|   status = sanei_usb_release_interface (device_number - 1, 0);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: could release interface 0 on invalid device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* remove mock device */
 | |
|   device_number--;
 | |
|   free (devices[device_number].devname);
 | |
|   devices[device_number].devname = NULL;
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** get id for all devices names
 | |
|  * loop on all existing devices and get vendor
 | |
|  * and product id by name.
 | |
|  * @param expected count
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_vendor_by_devname (void)
 | |
| {
 | |
|   int i;
 | |
|   SANE_Status status;
 | |
|   SANE_Word vendor, product;
 | |
|   device_list_type mock;
 | |
| 
 | |
|   /* loop on detected devices and open them */
 | |
|   for (i = 0; i < device_number; i++)
 | |
|     {
 | |
|       if (devices[i].missing == 0 && devices[i].devname != NULL)
 | |
| 	{
 | |
| 	  /* get device id */
 | |
| 	  status = sanei_usb_get_vendor_product_byname (devices[i].devname,
 | |
| 							&vendor, &product);
 | |
| 	  if (status != SANE_STATUS_GOOD)
 | |
| 	    {
 | |
| 	      printf ("ERROR: couldn't query device %s!\n",
 | |
| 		      devices[i].devname);
 | |
| 	      return 0;
 | |
| 	    }
 | |
| 	  if (vendor == 0 || product == 0)
 | |
| 	    {
 | |
| 	      printf ("ERROR: incomplete device id for %s!\n",
 | |
| 		      devices[i].devname);
 | |
| 	      return 0;
 | |
| 	    }
 | |
| 	  printf ("%s is %04x:%04x\n", devices[i].devname, vendor, product);
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* add mock device */
 | |
|   create_mock_device ("mock", &mock);
 | |
|   store_device (mock);
 | |
|   status = sanei_usb_get_vendor_product_byname ("mock", &vendor, &product);
 | |
|   if (status != SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: getting vendor for mock devname!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   if (vendor != mock.vendor || product != mock.product)
 | |
|     {
 | |
|       printf ("ERROR: wrong vendor/product for mock devname!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   /* remove mock device */
 | |
|   device_number--;
 | |
|   free (devices[device_number].devname);
 | |
|   devices[device_number].devname = NULL;
 | |
| 
 | |
|   /* try go get id for an invalid devname */
 | |
|   status = sanei_usb_get_vendor_product_byname ("invalid devname",
 | |
| 						&vendor, &product);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: unexpected success getting id for invalid devname!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   printf ("\n");
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** get vendor for all devices id
 | |
|  * loop on all existing devices and get vendor
 | |
|  * and product id.
 | |
|  * @param expected count
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_vendor_by_id (void)
 | |
| {
 | |
|   int i;
 | |
|   SANE_Status status;
 | |
|   SANE_Word vendor, product;
 | |
|   device_list_type mock;
 | |
| 
 | |
|   /* loop on detected devices and open them */
 | |
|   for (i = 0; i < device_number; i++)
 | |
|     {
 | |
|       if (devices[i].missing == 0 && devices[i].devname != NULL)
 | |
| 	{
 | |
| 	  /* get device id */
 | |
| 	  status = sanei_usb_get_vendor_product (i, &vendor, &product);
 | |
| 	  if (status != SANE_STATUS_GOOD)
 | |
| 	    {
 | |
| 	      printf ("ERROR: couldn't query device %d!\n", i);
 | |
| 	      return 0;
 | |
| 	    }
 | |
| 	  if (vendor == 0 || product == 0)
 | |
| 	    {
 | |
| 	      printf ("ERROR: incomplete device id for %d!\n", i);
 | |
| 	      return 0;
 | |
| 	    }
 | |
| 	  printf ("%d is %04x:%04x\n", i, vendor, product);
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* add mock device */
 | |
|   create_mock_device ("mock", &mock);
 | |
|   store_device (mock);
 | |
|   status =
 | |
|     sanei_usb_get_vendor_product (device_number - 1, &vendor, &product);
 | |
|   if (status != SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf ("ERROR: getting vendor for mock devname!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   if (vendor != mock.vendor || product != mock.product)
 | |
|     {
 | |
|       printf ("ERROR: wrong vendor/product for mock devname!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   /* remove mock device */
 | |
|   device_number--;
 | |
|   free (devices[device_number].devname);
 | |
|   devices[device_number].devname = NULL;
 | |
| 
 | |
|   /* try go get id for an invalid id */
 | |
|   status =
 | |
|     sanei_usb_get_vendor_product (device_number + 1, &vendor, &product);
 | |
|   if (status == SANE_STATUS_GOOD)
 | |
|     {
 | |
|       printf
 | |
| 	("ERROR: unexpected success getting vendor for invalid devname!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   printf ("\n");
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** test timeout functions : libusb only
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_timeout (void)
 | |
| {
 | |
| #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB)
 | |
|   int timeout = libusb_timeout;
 | |
| 
 | |
|   sanei_usb_set_timeout (5000);
 | |
|   if (libusb_timeout != 5000)
 | |
|     {
 | |
|       printf ("ERROR: failed to set timeout\n");
 | |
|       return 1;
 | |
|     }
 | |
|   sanei_usb_set_timeout (timeout);
 | |
| #endif
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /** test device scanning
 | |
|  * call sanei_usb_scan_devices, since it has no return code, no real
 | |
|  * assert can be done, but at least we can test it doesn't break
 | |
|  * other functions or don't leak memory
 | |
|  * @return always 1
 | |
|  */
 | |
| static int
 | |
| test_scan_devices (int detected, int opened)
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   printf ("rescanning for devices ...\n");
 | |
|   sanei_usb_scan_devices ();
 | |
|   rc = count_detected (detected);
 | |
|   if (!rc)
 | |
|     {
 | |
|       printf ("ERROR: scanning devices change detected count!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   rc = count_opened (opened);
 | |
|   if (!rc)
 | |
|     {
 | |
|       printf ("ERROR: scanning devices change opened count!\n");
 | |
|       return 0;
 | |
|     }
 | |
|   printf ("\n");
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * flag for dummy attach
 | |
|  */
 | |
| static int dummy_flag;
 | |
| 
 | |
| /**
 | |
|  * expected device name during attach
 | |
|  */
 | |
| static char *expected_device;
 | |
| 
 | |
| /** dummy attach function
 | |
|  * dummy attach function
 | |
|  * @return return SANE_STATUS_GOOD
 | |
|  */
 | |
| static SANE_Status
 | |
| dummy_attach (const char *dev)
 | |
| {
 | |
|   dummy_flag = (strcmp (expected_device, dev) == 0);
 | |
|   if (dummy_flag)
 | |
|     {
 | |
|       printf ("success attaching to %s...\n", dev);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       printf ("failed attaching to %s...\n", dev);
 | |
|     }
 | |
|   return SANE_STATUS_GOOD;
 | |
| }
 | |
| 
 | |
| /** test attaching usb device
 | |
|  * create a mock device and attach to it, checking
 | |
|  * if it is ok
 | |
|  * @return 1 on success, else 0
 | |
|  */
 | |
| static int
 | |
| test_attach (void)
 | |
| {
 | |
|   device_list_type mock;
 | |
| 
 | |
|   /* add mock device and try to attach to it */
 | |
|   dummy_flag = 0;
 | |
|   create_mock_device ("mock", &mock);
 | |
|   expected_device = mock.devname;
 | |
|   store_device (mock);
 | |
|   sanei_usb_attach_matching_devices ("usb 0xdead 0xbeef", dummy_attach);
 | |
| 
 | |
|   /* flag must be set */
 | |
|   if (dummy_flag != 1)
 | |
|     {
 | |
|       printf ("ERROR: couldn't attach to 'usb xdead 0xbeef' device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* attach by devname */
 | |
|   dummy_flag = 0;
 | |
|   sanei_usb_attach_matching_devices (mock.devname, dummy_attach);
 | |
|   /* flag must be set */
 | |
|   if (dummy_flag != 1)
 | |
|     {
 | |
|       printf ("ERROR: couldn't attach to 'mock' device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* attach to bogus device */
 | |
|   dummy_flag = 0;
 | |
|   sanei_usb_attach_matching_devices ("usb 0x0001 0x0001", dummy_attach);
 | |
| 
 | |
|   /* flag must not be set */
 | |
|   if (dummy_flag != 0)
 | |
|     {
 | |
|       printf ("ERROR: shouldn't be attached to bogus device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* attach by bogus devname */
 | |
|   sanei_usb_attach_matching_devices ("bogus", dummy_attach);
 | |
| 
 | |
|   /* flag must not be set */
 | |
|   if (dummy_flag != 0)
 | |
|     {
 | |
|       printf ("ERROR: shouldn't be attached to bogus device!\n");
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   /* remove mock device */
 | |
|   device_number--;
 | |
|   free (devices[device_number].devname);
 | |
|   devices[device_number].devname = NULL;
 | |
|   dummy_flag = 0;
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| int
 | |
| main (int __sane_unused__ argc, char **argv)
 | |
| {
 | |
|   int detected, opened, i;
 | |
|   SANE_Int dn[MAX_DEVICES];
 | |
| 
 | |
| #ifdef HAVE_LIBUSB_LEGACY
 | |
|   printf ("\n%s built with old libusb\n\n", argv[0]);
 | |
| #endif
 | |
| #ifdef HAVE_LIBUSB
 | |
|   printf ("\n%s built with libusb-1.0\n\n", argv[0]);
 | |
| #endif
 | |
| #ifdef HAVE_USBCALLS
 | |
|   printf ("\n%s built with usbcalls\n\n", argv[0]);
 | |
| #endif
 | |
| #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USBCALLS)
 | |
|   printf ("\n%s relying on deprecated scanner kernel module\n", argv[0]);
 | |
| #endif
 | |
| 
 | |
|   /* start sanei_usb */
 | |
|   assert (test_init (1));
 | |
| 
 | |
|   /* test timeout function */
 | |
|   assert (test_timeout ());
 | |
| 
 | |
|   /* count available devices */
 | |
|   detected = 0;
 | |
|   for (i = 0; i < device_number; i++)
 | |
|     {
 | |
|       if (devices[i].missing == 0 && devices[i].devname != NULL)
 | |
| 	{
 | |
| 	  detected++;
 | |
| 	}
 | |
|     }
 | |
|   printf ("%d devices found.\n", detected);
 | |
| 
 | |
|   /* rescan devices : detected count shouldn't change */
 | |
|   assert (test_scan_devices (detected, 0));
 | |
| 
 | |
|   /* test corner cases with mock device */
 | |
|   assert (test_store_device ());
 | |
| 
 | |
|   /* get vendor/product id for all available devices devname */
 | |
|   assert (test_vendor_by_devname ());
 | |
| 
 | |
|   /* get vendor/product id for all available devices id */
 | |
|   assert (test_vendor_by_id ());
 | |
| 
 | |
|   /* open all available devices */
 | |
|   assert (test_open_all (dn, detected));
 | |
| 
 | |
|   opened = get_opened();
 | |
| 
 | |
|   /* rescan devices : detected and opened count shouldn't change */
 | |
|   assert (test_scan_devices (detected, opened));
 | |
| 
 | |
|   /* try to open an inexisting device */
 | |
|   assert (test_open_invalid ());
 | |
| 
 | |
|   /* increase sanei _sub use count */
 | |
|   assert (test_init (2));
 | |
| 
 | |
|   /* there should be still as many detected devices */
 | |
|   assert (count_detected (detected));
 | |
| 
 | |
|   /* there should be still as many opened devices */
 | |
|   assert (count_opened (opened));
 | |
| 
 | |
|   assert (test_exit (1));
 | |
| 
 | |
|   /* there should be still as many opened devices */
 | |
|   assert (count_opened (opened));
 | |
| 
 | |
|   /* count devices again , sanei_usb_exit() shouldn't have
 | |
|    * change the count */
 | |
|   assert (count_detected (detected));
 | |
| 
 | |
|   /* claim all available devices */
 | |
|   assert (test_claim_all (dn, opened));
 | |
| 
 | |
|   /* then release them all */
 | |
|   assert (test_release_all (dn, opened));
 | |
| 
 | |
|   /* close all opened devices */
 | |
|   assert (test_close_all (dn, opened));
 | |
| 
 | |
|   /* check there is no opened device */
 | |
|   assert (count_opened (0));
 | |
| 
 | |
|   /* finally free resources */
 | |
|   assert (test_exit (0));
 | |
| 
 | |
|   /* check there is no more devices */
 | |
|   assert (count_detected (0));
 | |
| 
 | |
|   /* test attach matching device with a mock */
 | |
|   assert (test_attach ());
 | |
| 
 | |
|   /* try to call sanei_usb_exit() when it not initialized */
 | |
|   assert (test_exit (0));
 | |
| 
 | |
|   /* scan devices when sanei usb is not initialized */
 | |
|   assert (test_scan_devices (0, 0));
 | |
| 
 | |
|   /* we re start use of sanei usb so we check we have left it
 | |
|    * it he correct state after "closing" it. */
 | |
|   printf ("\n============================================================\n");
 | |
|   printf ("restart use of sanei usb after having freed all resources...\n\n");
 | |
|   assert (test_init (1));
 | |
| 
 | |
|   /* we should have the same initial count of detected devices */
 | |
|   assert (count_detected (detected));
 | |
| 
 | |
|   /* finally free resources */
 | |
|   assert (test_exit (0));
 | |
| 
 | |
|   /* all the tests are OK ! */
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
 |