mainusb.c


/*
 *
 * Code to implement some USB 2.0 HID 1.11 Full-speed device
 * running on a SiLabs C8051F342 or a C8051F346 microcontroller unit.
 *
 * This program was written by
 * Stephan K.H. Seidl <stephan.seidl@stfmc.de> in 2017,
 * no copyright is claimed.
 * It is offered as-is, without any warranty.
 * This program is in the public domain; do with it what you wish.
 *
 * The code below passed both the Chapter 9 Tests and the HID Tests provided
 * through the USB 2.0 tool USB2CV 1.5.4.2 with 0 Aborts, 0 Fails and
 * 0 Warnings each.
 *
 * The code below is based on the documents
 *
 * SiLabs C8051F340/1/2/3/4/5/6/7/8/9/A/B/C/D (C8051F34x) Rev. 1.4 9/09,
 * Copyright (C) 2009 by Silicon Laboratories,
 *
 * Universal Serial Bus Specification Revision 2.0 April 27, 2000
 * Copyright (C) 2000, Compaq Computer Corporation, Hewlett-Packard Company,
 * Intel Corporation, Lucent Technologies Inc, Microsoft Corporation,
 * NEC Corporation, Koninklijke Philips Electronics N.V.,
 *
 * Universal Serial Bus (USB) Device Class Definition for Human Interface
 * Devices (HID) Firmware Specification-6/27/01 Version 1.11
 * Copyright (C) 1996-2001 USB Implementers' Forum, and
 *
 * SiLabs AN249 Human Interface Device Tutorial Rev. 0.5 3/11
 * Copyright (C) 2011 by Silicon Laboratories.
 *
 * @(#)mainusb.c 1.3 - 2020-12-24 skhs
 *
 */

/****************************************************************************/

#if (0)
#define __C51__
#endif

#if (0)
#define _XC51_VER
#endif

#if (1)
#define IMPLEMENT_A_CRUNCHER_STUB
#endif

/****************************************************************************/

#if (defined (c_plusplus) || defined (__cplusplus))
extern "C" {
#endif

/****************************************************************************/

#define USB_DEVICE_IDVENDOR  (0x666c) /* Some illegal example VID. */
#define USB_DEVICE_IDPRODUCT (0x369c) /* Some illegal example PID. */
#define USB_DEVICE_BCDDEVICE (0x0100)

#define SYSTEM_CLOCK_BY_MEGA_C8051F342 (48)
#define SYSTEM_CLOCK_BY_MEGA_C8051F346 (24)
#define SYSTEM_CLOCK_BY_MEGA (SYSTEM_CLOCK_BY_MEGA_C8051F342)

/* See table 3.1. Global DC Electrical Characteristics in C8051F34x,
   plus 10mA for one external LED. */
#define USB_CONFIG_BMAXPOWER ((SYSTEM_CLOCK_BY_MEGA * 3 + 69) / 10)

#define FLASH_MEMORY_LAST_LEGAL_ADDRESS         (0xfbff)
#define FLASH_MEMORY_PAGE_SIZE                  (0x0200)
#define FLASH_MEMORY_SECURITY_LOCK_BYTE_ADDRESS (0xfbff)

#define TIMER2_OSCILLATOR_FREQUENCY ( (uint32_t) (SYSTEM_CLOCK_BY_MEGA) * \
                                      (uint32_t) (1000)                 * \
                                      (uint32_t) (1000) )
#define TIMER2_FREQUENCY_DIVISOR    (1)
#define TIMER2_INTERRUPT_FREQUENCY  (1000)

#define LED_PWM_ACTIVE_TIME_BY_MILLISECONDS      (   1)
#define LED_PWM_TOTAL_PERIOD_BY_MILLISECONDS     (  20)
#define LED_BLINKING_PERIOD_BY_MILLISECONDS_FAST ( 200)
#define LED_BLINKING_PERIOD_BY_MILLISECONDS_SLOW (2000)

#define MUCO_COMMUNICATIONS_BUFFER_DIM   (448)
#define MUCO_BYTECODE_STORAGE_MULTIPLIER (4)
#define MUCO_OPC_HELO                    (0x34)
#define MUCO_RC_SUCCESS                  (0x00)
#define MUCO_RC_CONTROLBLOCKDESTROYED    (0x42)
#define MUCO_RC_UNRECOVERABLEPROBLEM     (0x5f)

/****************************************************************************/

typedef unsigned char uint8_t;
#if (defined (__C51__))
typedef unsigned       int uint16_t;
typedef unsigned  long int uint32_t;
#elif (defined (_XC51_VER))
typedef unsigned       int uint16_t;
typedef unsigned  long int uint32_t;
#else
typedef unsigned short int uint16_t;
typedef unsigned       int uint32_t;
#endif

/****************************************************************************/

#if (defined (__C51__))
#define mycodeloc     code
#define mydataloc     xdata
#define mydatalocfast data
#elif (defined (_XC51_VER))
#define mycodeloc     _code
#define mydataloc     _xdata
#define mydatalocfast _data
#else
#define mycodeloc     /* */
#define mydataloc     /* */
#define mydatalocfast /* */
#endif

/****************************************************************************/

/* Pay attention.
   All the `mydatalocfast' type memory is used by the cruncher.
   So the `using' attribute cannot be applied here. */
#if (defined (__C51__))
#define ISR_PARAMS_TIMER2    interrupt  5 /* using 1 */
#define ISR_PARAMS_USB       interrupt  8 /* using 2 */
#define ISR_PARAMS_VBUSLEVEL interrupt 15 /* using 3 */
#elif (defined (_XC51_VER))
#define ISR_PARAMS_TIMER2    _interrupt  5 /* _using 1 */
#define ISR_PARAMS_USB       _interrupt  8 /* _using 2 */
#define ISR_PARAMS_VBUSLEVEL _interrupt 15 /* _using 3 */
#else
#define ISR_PARAMS_TIMER2    /* */
#define ISR_PARAMS_USB       /* */
#define ISR_PARAMS_VBUSLEVEL /* */
#endif

/****************************************************************************/

#if (defined (__C51__))
static volatile uint8_t mycodeloc securitylockbyte
  _at_ FLASH_MEMORY_SECURITY_LOCK_BYTE_ADDRESS;
#elif (defined (_XC51_VER))
static volatile uint8_t mycodeloc securitylockbyte
  _at FLASH_MEMORY_SECURITY_LOCK_BYTE_ADDRESS;
#else
static volatile uint8_t mycodeloc securitylockbyte
  = 0x82; /* All usable flash pages locked. */
#endif

/****************************************************************************/

#define DESCR_TYPE_DEVICE          (0x01)
#define DESCR_TYPE_CONFIGURATION   (0x02)
#define DESCR_TYPE_STRING          (0x03)
#define DESCR_TYPE_INTERFACE       (0x04)
#define DESCR_TYPE_ENDPOINT        (0x05)
#define DESCR_TYPE_DEVICEQUALIFIER (0x06)
#define DESCR_TYPE_OTHERSPEEDCONF  (0x07)
#define DESCR_TYPE_INTERFACEPOWER  (0x08)
#define DESCR_TYPE_HID             (0x21)
#define DESCR_TYPE_REPORT          (0x22)

/****************************************************************************/

#define USB_MAX_PACKET_LENGTH_EP0 (64)
#define USB_MAX_PACKET_LENGTH_EP1 (64)
#define USB_MAX_PACKET_LENGTH_EP2 (64)

/****************************************************************************/

typedef struct {
  uint8_t bLength;            /* Size of this descriptor in bytes.       */
  uint8_t bDescriptorType;    /* Device descriptor type = 1.             */
  uint8_t bcdUSB_lo;          /* USB specification release number (BCD). */
  uint8_t bcdUSB_hi;
  uint8_t bDeviceClass;       /* Class code (assigned by the USB-IF).    */
  uint8_t bDeviceSubClass;    /* Subclass code (assigned by the USB-IF). */
  uint8_t bDeviceProtocol;    /* Protocol code (assigned by the USB-IF). */
  uint8_t bMaxPacketSize0;    /* Maximum packet size for EP0.            */
  uint8_t idVendor_lo;        /* Vendor ID (assigned by the USB-IF).     */
  uint8_t idVendor_hi;
  uint8_t idProduct_lo;       /* Product ID (assigned by manufacturer).  */
  uint8_t idProduct_hi;
  uint8_t bcdDevice_lo;       /* Device release number (BCD).            */
  uint8_t bcdDevice_hi;
  uint8_t iManufacturer;      /* Index of the manufacturer string.       */
  uint8_t iProduct;           /* Index of the product string.            */
  uint8_t iSerialNumber;      /* Index of the serial number string.      */
  uint8_t bNumConfigurations; /* Number of possible configurations.      */
  } usbdevicedescriptor_t;

/****************************************************************************/

static const usbdevicedescriptor_t mycodeloc usbdevicedescriptor = {
  (uint8_t) sizeof (usbdevicedescriptor_t),
  DESCR_TYPE_DEVICE,
  0, /* bcdUSB_lo of bcdUSB = 2.00. */
  2, /* bcdUSB_hi of bcdUSB.        */
  0, /* bDeviceClass.               */
  0, /* bDeviceSubClass.            */
  0, /* bDeviceProtocol.            */
  USB_MAX_PACKET_LENGTH_EP0,
  (uint8_t) ((uint16_t) (USB_DEVICE_IDVENDOR )      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_DEVICE_IDVENDOR ) >> 8 & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_DEVICE_IDPRODUCT)      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_DEVICE_IDPRODUCT) >> 8 & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_DEVICE_BCDDEVICE)      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_DEVICE_BCDDEVICE) >> 8 & (uint16_t) 0xff),
  1, /* iManufacturer.              */
  2, /* iProduct.                   */
  3, /* iSerialNumber.              */
  1  /* bNumConfigurations.         */
  };

/****************************************************************************/

#define reportcountin  (USB_MAX_PACKET_LENGTH_EP1)
#define reportcountout (USB_MAX_PACKET_LENGTH_EP2)

/****************************************************************************/

static const uint8_t mycodeloc usbreportdescriptor [] = {
  0x06, 0x01, 0xff,     /* 0000-01-10: G Usage Page (Vendor-defined FF01)   */
  0x0a, 0x01, 0xff,     /* 0000-10-10: L Usage (Vendor-defined FF01)        */
  0xa1, 0x01,           /* 1010-00-01: M Collection (Application)           */
  0x06, 0x02, 0xff,     /* 0000-01-10: G   Usage Page (Vendor-defined FF02) */
  0x0a, 0x02, 0xff,     /* 0000-10-10: L   Usage (Vendor-defined FF02)      */
  0x15, 0,              /* 0001-01-01: G   Logical Minimum (0)              */
  0x26, 255, 0,         /* 0010-01-10: G   Logical Maximum (255),
                           two data bytes used to prevent a potential
                           problem with respect to signedness here          */
  0x75, 8,              /* 0111-01-01: G   Report Size (8)                  */
  0x95, reportcountin,  /* 1001-01-01: G   Report Count                     */
  0x81, 0<<0|1<<1|0<<2, /* 1000-00-01: M   Input (Data|Var|Abs)             */
  0x06, 0x03, 0xff,     /* 0000-01-10: G   Usage Page (Vendor-defined FF03) */
  0x0a, 0x03, 0xff,     /* 0000-10-10: L   Usage (Vendor-defined FF03)      */
  0x15, 0,              /* 0001-01-01: G   Logical Minimum (0)              */
  0x26, 255, 0,         /* 0010-01-10: G   Logical Maximum (255),
                           two data bytes used to prevent a potential
                           problem with respect to signedness here          */
  0x75, 8,              /* 0111-01-01: G   Report Size (8)                  */
  0x95, reportcountout, /* 1001-01-01: G   Report Count                     */
  0x91, 0<<0|1<<1|0<<2, /* 1001-00-01: M   Output (Data|Var|Abs)            */
  0x06, 0x04, 0xff,     /* 0000-01-10: G   Usage Page (Vendor-defined FF04) */
  0x0a, 0x04, 0xff,     /* 0000-10-10: L   Usage (Vendor-defined FF04)      */
  0x15, 0,              /* 0001-01-01: G   Logical Minimum (0)              */
  0x26, 255, 0,         /* 0010-01-10: G   Logical Maximum (255),
                           two data bytes used to prevent a potential
                           problem with respect to signedness here          */
  0x75, 8,              /* 0111-01-01: G   Report Size (8)                  */
  0x95, reportcountout, /* 1001-01-01: G   Report Count                     */
  0xb1, 0<<0|1<<1|0<<2, /* 1011-00-01: M   Feature (Data|Var|Abs)           */
  0xc0                  /* 1100-00-00: M   End Collection                   */
  };

/****************************************************************************/

#undef reportcountout
#undef reportcountin

/****************************************************************************/

typedef struct {
  uint8_t bLength;             /* Size of this descriptor in bytes.        */
  uint8_t bDescriptorType;     /* Configuration descriptor type = 2.       */
  uint8_t wTotalLength_lo;     /* Size of all data for this configuration. */
  uint8_t wTotalLength_hi;
  uint8_t bNumInterfaces;      /* Number of interfaces of this config.     */
  uint8_t bConfigurationValue; /* Identifier to select this configuration. */
  uint8_t iConfiguration;      /* Index of string describing this config.  */
  uint8_t bmAttributes;        /* Power source and wakeup settings.        */
  uint8_t bMaxPower;           /* Maximum power consumtion from the bus.   */
  } usbconfigdescriptor_t;

/****************************************************************************/

typedef struct {
  uint8_t bLength;            /* Size of this descriptor in bytes.          */
  uint8_t bDescriptorType;    /* Interface descriptor type = 4.             */
  uint8_t bInterfaceNumber;   /* Zero-based value identifying this iface.   */
  uint8_t bAlternateSetting;  /* Value used to select an alternate setting. */
  uint8_t bNumEndpoints;      /* Number of endpoints in addition to EP0.    */
  uint8_t bInterfaceClass;    /* Class code (assigned by the USB-IF).       */
  uint8_t bInterfaceSubclass; /* Subclass code (assigned by the USB-IF).    */
  uint8_t bInterfaceProtocol; /* Protocol code (assigned by the USB-IF).    */
  uint8_t iInterface;         /* Index of string describing this interface. */
  } usbinterfacedescriptor_t;

/****************************************************************************/

typedef struct {
  uint8_t bLength;                    /* Size of this descriptor in bytes.  */
  uint8_t bDescriptorType;            /* HID descriptor type = 0x21.        */
  uint8_t bcdHID_lo;                  /* HID class spec release number.     */
  uint8_t bcdHID_hi;
  uint8_t bCountryCode;               /* Country code localized hardware.   */
  uint8_t bNumDescriptors;            /* Number of HID report descriptors.  */
  uint8_t bHidRepDescriptorType;      /* HID report descriptor type = 0x22. */
  uint8_t bHidRepDescriptorLength_lo; /* Size of the HID report descriptor. */
  uint8_t bHidRepDescriptorLength_hi;
  } usbhiddescriptor_t;

/****************************************************************************/

typedef struct {
  uint8_t bLength;           /* Size of this descriptor in bytes.          */
  uint8_t bDescriptorType;   /* Endpoint descriptor type = 5.              */
  uint8_t bEndpointAddress;  /* Endpoint direction and number information. */
  uint8_t bmAttributes;      /* Transfer type supported.                   */
  uint8_t wMaxPacketSize_lo; /* Maximum packet size supported.             */
  uint8_t wMaxPacketSize_hi;
  uint8_t bInterval;         /* Polling interval in milliseconds.          */
  } usbendpointdescriptor_t;

/****************************************************************************/

/* For the sequence see
   section 7.1 Standard Requests in USB HID Ver 1.11. */
typedef struct {
  usbconfigdescriptor_t    usbconfigdescriptor;
  usbinterfacedescriptor_t usbinterfacedescriptor;
  usbhiddescriptor_t       usbhiddescriptor;
  usbendpointdescriptor_t  usbendpoint1descriptor;
  usbendpointdescriptor_t  usbendpoint2descriptor;
  } tcd_t;

/****************************************************************************/

/* For the sequence see
   section 7.1 Standard Requests in USB HID Ver 1.11. */
static const tcd_t mycodeloc tcd = { {

  (uint8_t) sizeof (usbconfigdescriptor_t),
  DESCR_TYPE_CONFIGURATION,
  (uint8_t) ((uint16_t) sizeof (tcd_t)      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) sizeof (tcd_t) >> 8 & (uint16_t) 0xff),
  1,    /* bNumInterfaces.                                             */
  1,    /* bConfigurationValue.                                        */
  4,    /* iConfiguration.                                             */
  0x80, /* bmAttributes = 1-0-0-00000 = bus-powered, no remote wakeup. */
  USB_CONFIG_BMAXPOWER

  }, {

  (uint8_t) sizeof (usbinterfacedescriptor_t),
  DESCR_TYPE_INTERFACE,
  0, /* bInterfaceNumber.                                             */
  0, /* bAlternateSetting,  no alternate setting.                     */
  2, /* bNumEndpoints,      number of endpoints in addition to EP0.   */
  3, /* bInterfaceClass,    HID class device.                         */
  0, /* bInterfaceSubclass, no boot device, hence, no subclass.       */
  0, /* bInterfaceProtocol, no subclass, hence, no specific protocol. */
  5  /* iInterface.                                                   */

  }, {

  (uint8_t) sizeof (usbhiddescriptor_t),
  DESCR_TYPE_HID,
  0x11, /* bcdHID_lo of bcdHID = 1.11.                       */
  0x01, /* bcdHID_hi of bcdHID.                              */
  0,    /* bCountryCode = 0, this hardware is not localized. */
  1,    /* bNumDescriptors.                                  */
  DESCR_TYPE_REPORT,
  (uint8_t) ((uint16_t) sizeof (usbreportdescriptor)      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) sizeof (usbreportdescriptor) >> 8 & (uint16_t) 0xff)

  }, {

  (uint8_t) sizeof (usbendpointdescriptor_t),
  DESCR_TYPE_ENDPOINT,
  0x81, /* bEndpointAddress = 1-000-0001 = IN1.                  */
  0x03, /* bmAttributes = 00-00-00-11 = Interrupt transfer type. */
  (uint8_t) ((uint16_t) (USB_MAX_PACKET_LENGTH_EP1)      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_MAX_PACKET_LENGTH_EP1) >> 8 & (uint16_t) 0xff),
  1     /* bInterval = 1ms.                                      */

  }, {

  (uint8_t) sizeof (usbendpointdescriptor_t),
  DESCR_TYPE_ENDPOINT,
  0x02, /* bEndpointAddress = 0-000-0010 = OUT2.                 */
  0x03, /* bmAttributes = 00-00-00-11 = Interrupt transfer type. */
  (uint8_t) ((uint16_t) (USB_MAX_PACKET_LENGTH_EP2)      & (uint16_t) 0xff),
  (uint8_t) ((uint16_t) (USB_MAX_PACKET_LENGTH_EP2) >> 8 & (uint16_t) 0xff),
  1     /* bInterval = 1ms.                                      */

  } };

/****************************************************************************/

typedef struct {
  uint8_t bLength;         /* Size of this descriptor in bytes. */
  uint8_t bDescriptorType; /* String descriptor type = 3.       */
  uint8_t bString [2];     /* UNICODE UTF-16LE encoded string.  */
  } usbtwostringdescriptor_t;

/****************************************************************************/

static const usbtwostringdescriptor_t mycodeloc usbstringsupportedlangs = {
  4,
  DESCR_TYPE_STRING,
  { 0x09, /* Low byte of USB LANGID = 0x0409 for US English. */
    0x04  /* High byte.                                      */
    }
  };

/****************************************************************************/

typedef struct {
  uint8_t bLength;         /* Size of this descriptor in bytes. */
  uint8_t bDescriptorType; /* String descriptor type = 3.       */
  uint8_t bString [144];   /* UNICODE UTF-16LE encoded string.  */
  } usbpaddedstringdescriptor_t;

/****************************************************************************/

#if (0)
s=""
s="${s}The name of the USB device manufacturer|"
s="${s}The product name of the USB device|"
s="${s}The serial number of the USB device|"
s="${s}Single USB 2.0 HID 1.11 Full-speed Configuration|"
s="${s}Vendor-defined HID 1.11 Interface with EP 1 IN and EP 2 OUT|"
s="${s}Some identifier of the application this USB device belongs to|"
s="${s}`date -u --rfc-3339=ns`|"
echo -n "${s}"                                         \
  | tr '|' '\012'                                      \
  | awk '{s0=$0;                                       \
          if(length(s0)>72)s0=substr(s0,1,72);         \
          st=s0;                                       \
          printf("  %d,\n",2*length(s0)+2);            \
          printf("  DESCR_TYPE_STRING,\n");            \
          while(length(s0)<72)s0=s0 "_";               \
          for(i=1;i<=length(s0);i++){                  \
            j=i%9;                                     \
            if(j==1&&i==1)printf("  {");               \
            if(j==1&&i!=1)printf("   ");               \
            printf(" %c%s%c, 0",39,substr(s0,i,1),39); \
            if(i!=length(s0))printf(",");              \
            if(i!=length(s0)&&j==0)printf("\n");       \
            if(i==length(s0))printf("\n");}            \
          printf("    } /* %s. */\n",st);              \
          printf("  };\n");}'                          \
  | cat
#endif

static const usbpaddedstringdescriptor_t mycodeloc usbstringmanufacturer = {
  80,
  DESCR_TYPE_STRING,
  { 'T', 0, 'h', 0, 'e', 0, ' ', 0, 'n', 0, 'a', 0, 'm', 0, 'e', 0, ' ', 0,
    'o', 0, 'f', 0, ' ', 0, 't', 0, 'h', 0, 'e', 0, ' ', 0, 'U', 0, 'S', 0,
    'B', 0, ' ', 0, 'd', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
    'm', 0, 'a', 0, 'n', 0, 'u', 0, 'f', 0, 'a', 0, 'c', 0, 't', 0, 'u', 0,
    'r', 0, 'e', 0, 'r', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* The name of the USB device manufacturer. */
  };

static const usbpaddedstringdescriptor_t mycodeloc usbstringproduct = {
  70,
  DESCR_TYPE_STRING,
  { 'T', 0, 'h', 0, 'e', 0, ' ', 0, 'p', 0, 'r', 0, 'o', 0, 'd', 0, 'u', 0,
    'c', 0, 't', 0, ' ', 0, 'n', 0, 'a', 0, 'm', 0, 'e', 0, ' ', 0, 'o', 0,
    'f', 0, ' ', 0, 't', 0, 'h', 0, 'e', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0,
    ' ', 0, 'd', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* The product name of the USB device. */
  };

static const usbpaddedstringdescriptor_t mycodeloc usbstringserialnumber = {
  72,
  DESCR_TYPE_STRING,
  { 'T', 0, 'h', 0, 'e', 0, ' ', 0, 's', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0,
    'l', 0, ' ', 0, 'n', 0, 'u', 0, 'm', 0, 'b', 0, 'e', 0, 'r', 0, ' ', 0,
    'o', 0, 'f', 0, ' ', 0, 't', 0, 'h', 0, 'e', 0, ' ', 0, 'U', 0, 'S', 0,
    'B', 0, ' ', 0, 'd', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* The serial number of the USB device. */
  };

static const usbpaddedstringdescriptor_t mycodeloc usbstringconfiguration = {
  98,
  DESCR_TYPE_STRING,
  { 'S', 0, 'i', 0, 'n', 0, 'g', 0, 'l', 0, 'e', 0, ' ', 0, 'U', 0, 'S', 0,
    'B', 0, ' ', 0, '2', 0, '.', 0, '0', 0, ' ', 0, 'H', 0, 'I', 0, 'D', 0,
    ' ', 0, '1', 0, '.', 0, '1', 0, '1', 0, ' ', 0, 'F', 0, 'u', 0, 'l', 0,
    'l', 0, '-', 0, 's', 0, 'p', 0, 'e', 0, 'e', 0, 'd', 0, ' ', 0, 'C', 0,
    'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0, 'u', 0, 'r', 0, 'a', 0, 't', 0,
    'i', 0, 'o', 0, 'n', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* Single USB 2.0 HID 1.11 Full-speed Configuration. */
  };

static const usbpaddedstringdescriptor_t mycodeloc usbstringinterface = {
  120,
  DESCR_TYPE_STRING,
  { 'V', 0, 'e', 0, 'n', 0, 'd', 0, 'o', 0, 'r', 0, '-', 0, 'd', 0, 'e', 0,
    'f', 0, 'i', 0, 'n', 0, 'e', 0, 'd', 0, ' ', 0, 'H', 0, 'I', 0, 'D', 0,
    ' ', 0, '1', 0, '.', 0, '1', 0, '1', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0,
    'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, ' ', 0, 'w', 0, 'i', 0,
    't', 0, 'h', 0, ' ', 0, 'E', 0, 'P', 0, ' ', 0, '1', 0, ' ', 0, 'I', 0,
    'N', 0, ' ', 0, 'a', 0, 'n', 0, 'd', 0, ' ', 0, 'E', 0, 'P', 0, ' ', 0,
    '2', 0, ' ', 0, 'O', 0, 'U', 0, 'T', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* Vendor-defined HID 1.11 Interface with EP 1 IN and EP 2 OUT. */
  };

/****************************************************************************/

static const usbpaddedstringdescriptor_t mycodeloc hiddenapplicationid = {
  124,
  DESCR_TYPE_STRING,
  { 'S', 0, 'o', 0, 'm', 0, 'e', 0, ' ', 0, 'i', 0, 'd', 0, 'e', 0, 'n', 0,
    't', 0, 'i', 0, 'f', 0, 'i', 0, 'e', 0, 'r', 0, ' ', 0, 'o', 0, 'f', 0,
    ' ', 0, 't', 0, 'h', 0, 'e', 0, ' ', 0, 'a', 0, 'p', 0, 'p', 0, 'l', 0,
    'i', 0, 'c', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0, ' ', 0, 't', 0,
    'h', 0, 'i', 0, 's', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0, ' ', 0, 'd', 0,
    'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0, 'b', 0, 'e', 0, 'l', 0,
    'o', 0, 'n', 0, 'g', 0, 's', 0, ' ', 0, 't', 0, 'o', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* Some identifier of the application this USB device belongs to. */
  };

static const usbpaddedstringdescriptor_t mycodeloc hiddenreleasedate = {
  72,
  DESCR_TYPE_STRING,
  { '2', 0, '0', 0, '1', 0, '7', 0, '-', 0, '0', 0, '8', 0, '-', 0, '2', 0,
    '1', 0, ' ', 0, '1', 0, '2', 0, ':', 0, '0', 0, '0', 0, ':', 0, '0', 0,
    '0', 0, '.', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0,
    '0', 0, '0', 0, '+', 0, '0', 0, '0', 0, ':', 0, '0', 0, '0', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0,
    '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0, '_', 0
    } /* 2017-08-21 12:00:00.000000000+00:00. */
  };

/****************************************************************************/

static const uint8_t mycodeloc numberofusbstrings = 8;

/****************************************************************************/

#define timer2oscillatorfrequency  ((uint32_t) (TIMER2_OSCILLATOR_FREQUENCY))
#define timer2frequencydivisor     ((uint32_t) (TIMER2_FREQUENCY_DIVISOR   ))
#define timer2interruptfrequency   ((uint32_t) (TIMER2_INTERRUPT_FREQUENCY ))
#define timer2reloadminuend        ((uint32_t) 0x10000)
#define timer2reloadsubtrahendnum1 ( (timer2oscillatorfrequency ) )
#define timer2reloadsubtrahendden1 ( (timer2frequencydivisor    ) * \
                                     (timer2interruptfrequency  ) )
#define timer2reloadsubtrahendnum2 ( (timer2reloadsubtrahendnum1) + \
                                     (timer2reloadsubtrahendnum1) + \
                                     (timer2reloadsubtrahendden1) )
#define timer2reloadsubtrahendden2 ( (timer2reloadsubtrahendden1) + \
                                     (timer2reloadsubtrahendden1) )
#define timer2reloadsubtrahend     ( (timer2reloadsubtrahendnum2) / \
                                     (timer2reloadsubtrahendden2) )
#define timer2reload32 (                             \
  (timer2reloadminuend) < (timer2reloadsubtrahend) ? \
  (uint32_t) 0                                     : \
  (timer2reloadminuend) - (timer2reloadsubtrahend)   \
  )

/****************************************************************************/

static const uint8_t mycodeloc timer2reload [2] = {
  (uint8_t) ((timer2reload32)      & (uint32_t) 0xff),
  (uint8_t) ((timer2reload32) >> 8 & (uint32_t) 0xff)
  };

/****************************************************************************/

#undef timer2reload32
#undef timer2reloadsubtrahend
#undef timer2reloadsubtrahendden2
#undef timer2reloadsubtrahendnum2
#undef timer2reloadsubtrahendden1
#undef timer2reloadsubtrahendnum1
#undef timer2reloadminuend
#undef timer2interruptfrequency
#undef timer2frequencydivisor
#undef timer2oscillatorfrequency

/****************************************************************************/

#if (defined (__C51__))
#define mysfr8declarator             sfr
#define mysfr1declarator             sbit
#define mysfr1initializer(base, bit) base ^ bit
#elif (defined (_XC51_VER))
#define mysfr8declarator             _sfr
#define mysfr1declarator             _sfrbit
#define mysfr1initializer(base, bit) base ^ bit
#else
#define mysfr8declarator             static volatile uint8_t
#define mysfr1declarator             static volatile uint8_t
#define mysfr1initializer(base, bit) 0
#endif
mysfr8declarator mysfr8_P0      = 0x80; /* Port0 Latch                     */
mysfr8declarator mysfr8_PCON    = 0x87; /* Power Control                   */
mysfr8declarator mysfr8_TCON    = 0x88; /* Timer Control                   */
mysfr8declarator mysfr8_TMOD    = 0x89; /* Timer Mode                      */
mysfr8declarator mysfr8_TL0     = 0x8a; /* Timer 0 Low Byte                */
mysfr8declarator mysfr8_TH0     = 0x8c; /* Timer 0 High Byte               */
mysfr8declarator mysfr8_CKCON   = 0x8e; /* Clock Control                   */
mysfr8declarator mysfr8_PSCTL   = 0x8f; /* Program Store R/W Control       */
mysfr8declarator mysfr8_USB0ADR = 0x96; /* USB0 Indirect Address           */
mysfr8declarator mysfr8_USB0DAT = 0x97; /* USB0 Data                       */
mysfr8declarator mysfr8_P0MDOUT = 0xa4; /* Port0 Output Mode               */
mysfr8declarator mysfr8_IE      = 0xa8; /* Interrupt Enable                */
mysfr8declarator mysfr8_CLKSEL  = 0xa9; /* Clock Select                    */
mysfr8declarator mysfr8_PFE0CN  = 0xaf; /* Prefetch Engine Control         */
mysfr8declarator mysfr8_OSCXCN  = 0xb1; /* External Oscillator Control     */
mysfr8declarator mysfr8_OSCICN  = 0xb2; /* Internal H-F Oscillator Control */
mysfr8declarator mysfr8_FLSCL   = 0xb6; /* Flash Scale                     */
mysfr8declarator mysfr8_FLKEY   = 0xb7; /* Flash Lock and Key              */
mysfr8declarator mysfr8_IP      = 0xb8; /* Interrupt Priority              */
mysfr8declarator mysfr8_CLKMUL  = 0xb9; /* Clock Multiplier Control        */
mysfr8declarator mysfr8_TMR2CN  = 0xc8; /* Timer 2 Control                 */
mysfr8declarator mysfr8_REG0CN  = 0xc9; /* Voltage Regulator Control       */
mysfr8declarator mysfr8_TMR2RLL = 0xca; /* Timer 2 Reload Reg Low Byte     */
mysfr8declarator mysfr8_TMR2RLH = 0xcb; /* Timer 2 Reload Reg High Byte    */
mysfr8declarator mysfr8_TMR2L   = 0xcc; /* Timer 2 Low Byte                */
mysfr8declarator mysfr8_TMR2H   = 0xcd; /* Timer 2 High Byte               */
mysfr8declarator mysfr8_P0SKIP  = 0xd4; /* Port0 Skip                      */
mysfr8declarator mysfr8_USB0XCN = 0xd7; /* USB0 Transceiver Control        */
mysfr8declarator mysfr8_PCA0MD  = 0xd9; /* PCA Mode                        */
mysfr8declarator mysfr8_XBR1    = 0xe2; /* Port I/O Crossbar Register 1    */
mysfr8declarator mysfr8_EIE1    = 0xe6; /* Extended Interrupt Enable 1     */
mysfr8declarator mysfr8_EIE2    = 0xe7; /* Extended Interrupt Enable 2     */
mysfr8declarator mysfr8_RSTSRC  = 0xef; /* Reset Source                    */
mysfr8declarator mysfr8_P0MDIN  = 0xf1; /* Port0 Input Mode                */
mysfr8declarator mysfr8_EIP1    = 0xf6; /* Extended Interrupt Priority 1   */
mysfr8declarator mysfr8_EIP2    = 0xf7; /* Extended Interrupt Priority 2   */
mysfr8declarator mysfr8_VDM0CN  = 0xff; /* VDD Monitor Control             */
mysfr1declarator mysfr1_P0DOT2  = mysfr1initializer (mysfr8_P0,     2);
mysfr1declarator mysfr1_P0DOT1  = mysfr1initializer (mysfr8_P0,     1);
mysfr1declarator mysfr1_P0DOT0  = mysfr1initializer (mysfr8_P0,     0);
mysfr1declarator mysfr1_TR0     = mysfr1initializer (mysfr8_TCON,   4);
mysfr1declarator mysfr1_EA      = mysfr1initializer (mysfr8_IE,     7);
mysfr1declarator mysfr1_ET2     = mysfr1initializer (mysfr8_IE,     5);
mysfr1declarator mysfr1_ET0     = mysfr1initializer (mysfr8_IE,     1);
mysfr1declarator mysfr1_PT2     = mysfr1initializer (mysfr8_IP,     5);
mysfr1declarator mysfr1_PT0     = mysfr1initializer (mysfr8_IP,     1);
mysfr1declarator mysfr1_TF2H    = mysfr1initializer (mysfr8_TMR2CN, 7);
mysfr1declarator mysfr1_TF2LEN  = mysfr1initializer (mysfr8_TMR2CN, 5);
mysfr1declarator mysfr1_T2CE    = mysfr1initializer (mysfr8_TMR2CN, 4);
mysfr1declarator mysfr1_T2SPLIT = mysfr1initializer (mysfr8_TMR2CN, 3);
mysfr1declarator mysfr1_TR2     = mysfr1initializer (mysfr8_TMR2CN, 2);
#undef mysfr1initializer
#undef mysfr1declarator
#undef mysfr8declarator

/****************************************************************************/

#define MSFR8_STOP     (0x02) /* PCON: Stop Mode Select                     */
#define MSFR8_IDLE     (0x01) /* PCON: Idle Mode Select                     */
#define MSFR8_T2ML     (0x10) /* CKCON: Timer 2 Low Byte Clock Select       */
#define MSFR8_PSEE     (0x02) /* PSCTL: Program Store Erase Enable          */
#define MSFR8_PSWE     (0x01) /* PSCTL: Program Store Write Enable          */
#define MSFR8_USB0BUSY (0x80) /* USB0ADR: USB0 Register Read Busy Flag      */
#define MSFR8_AUTORD   (0x40) /* USB0ADR: USB0 Register Auto-read Flag      */
#define MSFR8_USBCLK2  (0x40) /* CLKSEL: USB Clock Select                   */
#define MSFR8_USBCLK1  (0x20) /* CLKSEL: USB Clock Select                   */
#define MSFR8_USBCLK0  (0x10) /* CLKSEL: USB Clock Select                   */
#define MSFR8_CLKSL2   (0x04) /* CLKSEL: System Clock Select                */
#define MSFR8_CLKSL1   (0x02) /* CLKSEL: System Clock Select                */
#define MSFR8_CLKSL0   (0x01) /* CLKSEL: System Clock Select                */
#define MSFR8_PFEN     (0x20) /* PFE0CN: Prefetch Enable                    */
#define MSFR8_FLBWE    (0x01) /* PFE0CN: Flash Block Write Enable           */
#define MSFR8_XTLVLD   (0x80) /* OSCXCN: Crystal Oscillator Valid Flag      */
#define MSFR8_XOSCMD2  (0x40) /* OSCXCN: External Oscillator Mode Bits      */
#define MSFR8_XOSCMD1  (0x20) /* OSCXCN: External Oscillator Mode Bits      */
#define MSFR8_XOSCMD0  (0x10) /* OSCXCN: External Oscillator Mode Bits      */
#define MSFR8_XFCN2    (0x04) /* OSCXCN: External Oscill Freq Control Bits  */
#define MSFR8_XFCN1    (0x02) /* OSCXCN: External Oscill Freq Control Bits  */
#define MSFR8_XFCN0    (0x01) /* OSCXCN: External Oscill Freq Control Bits  */
#define MSFR8_IOSCEN   (0x80) /* OSCICN: Internal H-F Oscill Enable Bit     */
#define MSFR8_IFRDY    (0x40) /* OSCICN: Internal H-F Oscill Freq Ready     */
#define MSFR8_SUSPEND  (0x20) /* OSCICN: Stop the Internal H-F Oscill       */
#define MSFR8_IFCN1    (0x02) /* OSCICN: Internal H-F Oscill Freq Control   */
#define MSFR8_IFCN0    (0x01) /* OSCICN: Internal H-F Oscill Freq Control   */
#define MSFR8_FOSE     (0x80) /* FLSCL: FLASH One-shot Enable               */
#define MSFR8_FLRT     (0x10) /* FLSCL: FLASH Read Time                     */
#define MSFR8_MULEN    (0x80) /* CLKMUL: Clock Multiplier Enable            */
#define MSFR8_MULINIT  (0x40) /* CLKMUL: Clock Multiplier Initialize        */
#define MSFR8_MULRDY   (0x20) /* CLKMUL: Clock Multiplier Ready             */
#define MSFR8_MULSEL1  (0x02) /* CLKMUL: Clock Multiplier Input Select      */
#define MSFR8_MULSEL0  (0x01) /* CLKMUL: Clock Multiplier Input Select      */
#define MSFR8_REGDIS   (0x80) /* REG0CN: Voltage Regulator Disable          */
#define MSFR8_VBSTAT   (0x40) /* REG0CN: VBUS Signal Status                 */
#define MSFR8_REGMOD   (0x10) /* REG0CN: Voltage Regulator Mode Select      */
#define MSFR8_PREN     (0x80) /* USB0XCN: Internal Pull-up Resistor Enable  */
#define MSFR8_PHYEN    (0x40) /* USB0XCN: Physical Layer Enable             */
#define MSFR8_SPEED    (0x20) /* USB0XCN: USB0 Speed Select                 */
#define MSFR8_WDTE     (0x40) /* PCA0MD: Watchdog Timer Enable              */
#define MSFR8_ECF      (0x01) /* PCA0MD: PCA Counter/Timer Ovfl Int Enable  */
#define MSFR8_XBARE    (0x40) /* XBR1: Crossbar Enable                      */
#define MSFR8_EUSB0    (0x02) /* EIE1: Enable USB0 Interrupt                */
#define MSFR8_EVBUS    (0x01) /* EIE2: Enable VBUS Level Interrupt          */
#define MSFR8_USBRSF   (0x80) /* RSTSRC: USB Reset Enable/Flag              */
#define MSFR8_C0RSEF   (0x20) /* RSTSRC: Comparator0 Reset Enable/Flag      */
#define MSFR8_SWRSF    (0x10) /* RSTSRC: Software Reset Force/Flag          */
#define MSFR8_MCDRSF   (0x04) /* RSTSRC: Missing Clock Reset Enable/Flag    */
#define MSFR8_PORSF    (0x02) /* RSTSRC: VDD Monitor Reset Enable / PO Flag */
#define MSFR8_PVBUS    (0x01) /* EIP2: VBUS Level Int Priority Control      */
#define MSFR8_VDMEN    (0x80) /* VDM0CN: VDD Monitor Enable                 */
#define MSFR8_VDDSTAT  (0x40) /* VDM0CN: VDD Status                         */

/****************************************************************************/

#define CUSB8_FADDR    (0x00) /* USB0 Function Address                      */
#define CUSB8_POWER    (0x01) /* USB0 Power Management                      */
#define CUSB8_IN1INT   (0x02) /* USB0 EP0 and EP1-3 IN Interrupt Flags      */
#define CUSB8_OUT1INT  (0x04) /* USB0 EP1-3 OUT Interrupt Flags             */
#define CUSB8_CMINT    (0x06) /* USB0 Common Interrupt Flags                */
#define CUSB8_IN1IE    (0x07) /* USB0 EP0 and EP1-3 IN Interrupt Enable     */
#define CUSB8_OUT1IE   (0x09) /* USB0 EP1-3 OUT Interrupt Enable            */
#define CUSB8_CMIE     (0x0b) /* USB0 Common Interrupt Enables              */
#define CUSB8_INDEX    (0x0e) /* USB0 Endpoint Index Selection   (-->INDEX) */
#define CUSB8_CLKREC   (0x0f) /* USB0 Clock Recovery Control                */
#define CUSB8_E0CSR    (0x11) /* USB0 EP0 Cntrl/Stat                (INDEX) */
#define CUSB8_EINCSRL  (0x11) /* USB0 EP1-3 IN Cntrl/Stat Lo Byte   (INDEX) */
#define CUSB8_EINCSRH  (0x12) /* USB0 EP1-3 IN Cntrl/Stat Hi Byte   (INDEX) */
#define CUSB8_EOUTCSRL (0x14) /* USB0 EP1-3 OUT Cntrl/Stat Lo Byte  (INDEX) */
#define CUSB8_EOUTCSRH (0x15) /* USB0 EP1-3 OUT Cntrl/Stat Hi Byte  (INDEX) */
#define CUSB8_E0CNT    (0x16) /* USB0 EP0 OUT Recvd Count           (INDEX) */
#define CUSB8_EOUTCNTL (0x16) /* USB0 EP1-3 OUT Recvd Count Lo Byte (INDEX) */
#define CUSB8_EOUTCNTH (0x17) /* USB0 EP1-3 OUT Recvd Count Hi Byte (INDEX) */
#define CUSB8_FIFO0    (0x20) /* USB0 EP0 FIFO Access                       */
#define CUSB8_FIFO1    (0x21) /* USB0 EP1 FIFO Access                       */
#define CUSB8_FIFO2    (0x22) /* USB0 EP2 FIFO Access                       */

/****************************************************************************/

#define MUSB8_USBINH   (0x10) /* POWER: USB0 Inhibit                     */
#define MUSB8_USBRST   (0x08) /* POWER: USB0 Reset Detect                */
#define MUSB8_RESUME   (0x04) /* POWER: USB0 Force Resume                */
#define MUSB8_SUSEN    (0x01) /* POWER: USB0 Suspend Detection Enable    */
#define MUSB8_IN1      (0x02) /* IN1INT: IN EP1 Interrupt-pending Flag   */
#define MUSB8_EP0      (0x01) /* IN1INT: EP0 Interrupt-pending Flag      */
#define MUSB8_OUT2     (0x04) /* OUT1INT: OUT EP2 Interrupt-pending Flag */
#define MUSB8_RSTINT   (0x04) /* CMINT: Reset Interrupt-pending Flag     */
#define MUSB8_RSUINT   (0x02) /* CMINT: Resume Interrupt-pending Flag    */
#define MUSB8_SUSINT   (0x01) /* CMINT: Suspend Interrupt-pending Flag   */
#define MUSB8_IN3E     (0x08) /* IN1IE: IN EP3 Interrupt Enable          */
#define MUSB8_IN2E     (0x04) /* IN1IE: IN EP2 Interrupt Enable          */
#define MUSB8_IN1E     (0x02) /* IN1IE: IN EP1 Interrupt Enable          */
#define MUSB8_EP0E     (0x01) /* IN1IE: EP0 Interrupt Enable             */
#define MUSB8_OUT3E    (0x08) /* OUT1IE: OUT EP3 Interrupt Enable        */
#define MUSB8_OUT2E    (0x04) /* OUT1IE: OUT EP2 Interrupt Enable        */
#define MUSB8_OUT1E    (0x02) /* OUT1IE: OUT EP1 Interrupt Enable        */
#define MUSB8_SOFE     (0x08) /* CMIE: Start of Frame Interrupt Enable   */
#define MUSB8_RSTINTE  (0x04) /* CMIE: Reset Interrupt Enable            */
#define MUSB8_RSUINTE  (0x02) /* CMIE: Resume Interrupt Enable           */
#define MUSB8_SUSINTE  (0x01) /* CMIE: Suspend Interrupt Enable          */
#define MUSB8_EPSEL    (0x0f) /* INDEX: Endpoint Select                  */
#define MUSB8_CRE      (0x80) /* CLKREC: Clock Recovery Enable           */
#define MUSB8_SSUEND   (0x80) /* E0CSR: Serviced Setup End               */
#define MUSB8_SOPRDY   (0x40) /* E0CSR: Serviced OPRDY                   */
#define MUSB8_SDSTL    (0x20) /* E0CSR: Send Stall                       */
#define MUSB8_SUEND    (0x10) /* E0CSR: Setup End                        */
#define MUSB8_DATAEND  (0x08) /* E0CSR: Data End                         */
#define MUSB8_STSTL    (0x04) /* E0CSR: Sent Stall                       */
#define MUSB8_INPRDY   (0x02) /* E0CSR: IN Packet Ready                  */
#define MUSB8_OPRDY    (0x01) /* E0CSR: OUT Packet Ready                 */
#define MUSB8_INCLRDT  (0x40) /* EINCSRL: Clear Data Toggle              */
#define MUSB8_INSTSTL  (0x20) /* EINCSRL: Sent Stall                     */
#define MUSB8_INSDSTL  (0x10) /* EINCSRL: Send Stall                     */
#define MUSB8_INFLUSH  (0x08) /* EINCSRL: FIFO Flush                     */
#define MUSB8_ININPRDY (0x01) /* EINCSRL: IN Packet Ready                */
#define MUSB8_DIRSEL   (0x20) /* EINCSRH: Endpoint Direction Select      */
#define MUSB8_FCDT     (0x08) /* EINCSRH: Force Data Toggle              */
#define MUSB8_OUTCLRDT (0x80) /* EOUTCSRL: Clear Data Toggle             */
#define MUSB8_OUTSTSTL (0x40) /* EOUTCSRL: Sent Stall                    */
#define MUSB8_OUTSDSTL (0x20) /* EOUTCSRL: Send Stall                    */
#define MUSB8_OUTFLUSH (0x10) /* EOUTCSRL: FIFO Flush                    */
#define MUSB8_FIFOFUL  (0x02) /* EOUTCSRL: OUT FIFO Full                 */
#define MUSB8_OUTOPRDY (0x01) /* EOUTCSRL: OUT Packet Ready              */

/****************************************************************************/

static volatile uint32_t mydataloc timerstateaugmentation [2] = { 0, 0 };

/****************************************************************************/

static volatile uint8_t mydataloc numbercrunchingrequestedorperforming = 0;
static volatile uint8_t mydataloc numbercruncherbufferprobablydestroyed = 0;

/****************************************************************************/

typedef enum {
  devStateDefault    = 1,
  devStateAddress    = 2,
  devStateConfigured = 3
  } devstate_t;

/****************************************************************************/

static volatile devstate_t mydataloc devstate = devStateDefault;

/****************************************************************************/

typedef enum {
  ep0stateIdle         = 1,
  ep0stateTransmitting = 2,
  ep0stateReceiving    = 3,
  ep0stateStalling     = 4
  } ep0state_t;

/****************************************************************************/

static volatile struct {
  const uint8_t mycodeloc    *pc;
  volatile uint8_t mydataloc *pv;
  uint16_t                   bytesfromdevice;
  uint16_t                   zerosfromdevice;
  uint16_t                   bytesfromhosttodiscard;
  uint16_t                   wValue;
  uint16_t                   wIndex;
  uint16_t                   wLength;
  ep0state_t                 state;
  uint8_t                    useep0insteadofep1;
  uint8_t                    manuallytriggeredep1shipping;
  uint8_t                    cmint;
  uint8_t                    in1int;
  uint8_t                    out1int;
  uint8_t                    e0csr;
  uint8_t                    eincsrl;
  uint8_t                    eincsrh;
  uint8_t                    eoutcsrl;
  uint8_t                    eoutcsrh;
  uint8_t                    cnt0ststl;
  uint8_t                    cntin1int;
  uint8_t                    buf [USB_MAX_PACKET_LENGTH_EP0];
  uint8_t                    bmRequestType;
  uint8_t                    bRequest;
  uint8_t                    wValue_lo;
  uint8_t                    wValue_hi;
  uint8_t                    wIndex_lo;
  uint8_t                    wIndex_hi;
  uint8_t                    wLength_lo;
  uint8_t                    wLength_hi;
  } mydataloc ep0 = { 0, 0, 0, 0, 0, 0, 0, 0, ep0stateIdle,
                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

/****************************************************************************/

typedef enum {
  ep12haltstateHalted  = 1,
  ep12haltstateRunning = 2
  } ep12haltstate_t;

/****************************************************************************/

typedef enum {
  ep12commstateIdle                = 1,
  ep12commstateWaitingForReception = 2,
  ep12commstateCrunchingOrCrunched = 3,
  ep12commstateWaitingForShipping  = 4
  } ep12commstate_t;

/****************************************************************************/

typedef struct {
  uint16_t          dim;
  uint16_t          cntk1;
  uint16_t          cntk2;
  uint8_t           buf3 [3];
  uint8_t           opc;
  uint8_t mydataloc *buf0;
  uint8_t mydataloc *bufk;
  ep12haltstate_t   haltstate1;
  ep12haltstate_t   haltstate2;
  ep12commstate_t   commstate;
  } ep12_t;

/****************************************************************************/

static volatile ep12_t mydataloc ep12 = {
  0, 0, 0, { 0, 0, 0 }, 0, 0, 0,
  ep12haltstateHalted, ep12haltstateHalted, ep12commstateIdle
  };
static volatile ep12_t mydataloc ep12latch = {
  0, 0, 0, { 0, 0, 0 }, 0, 0, 0,
  ep12haltstateHalted, ep12haltstateHalted, ep12commstateIdle
  };

/****************************************************************************/

#if (defined (IMPLEMENT_A_CRUNCHER_STUB))
static uint8_t mydataloc combuf [
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM
  ];
static const uint16_t mycodeloc dimcombuf =
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM
  ;
static uint8_t mydataloc bytecode [
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM *
  (uint16_t) MUCO_BYTECODE_STORAGE_MULTIPLIER
  ];
static const uint16_t mycodeloc dimbytecode =
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM *
  (uint16_t) MUCO_BYTECODE_STORAGE_MULTIPLIER
  ;
static const uint8_t mycodeloc remaininglevel12updates = 100;
static const uint8_t mycodeloc updatekeyenable [3] = { 1, 1, 1 };
static uint8_t mydataloc protocolstate = 0x80;
#else
extern uint8_t mydataloc combuf [
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM
  ];
static const uint16_t mycodeloc dimcombuf =
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM
  ;
extern uint8_t mydataloc bytecode [
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM *
  (uint16_t) MUCO_BYTECODE_STORAGE_MULTIPLIER
  ];
static const uint16_t mycodeloc dimbytecode =
  (uint16_t) MUCO_COMMUNICATIONS_BUFFER_DIM *
  (uint16_t) MUCO_BYTECODE_STORAGE_MULTIPLIER
  ;
extern const uint8_t mycodeloc remaininglevel12updates;
extern const uint8_t mycodeloc updatekeyenable [3];
extern uint8_t mydataloc protocolstate;
#endif

/****************************************************************************/

/* If the HID idle rate equals zero, then the duration is indefinite.
   The endpoint will inhibit reporting forever, only reporting
   when a change is detected in the report data.
   This is the recommended default idle rate for joysticks and
   mice, see section 7.2.4 Set_Idle Request in USB HID Ver 1.11. */
static volatile uint8_t mydataloc hidcurrentidlerate = 0;

/****************************************************************************/

#define                                                   \
macCrc16(n, pbuf, pcrc)                                   \
{                                                         \
  uint16_t mydataloc crc, i, u, v, xnz;                   \
  uint8_t mydataloc j, k;                                 \
                                                          \
  crc = 0xffff;                                           \
  for (i = 0; i < (n); i++) {                             \
    u = (uint16_t) *((pbuf) + i);                         \
    v = 0x0080;                                           \
    for (j = 0; j < 8; j++) {                             \
      xnz = crc & (uint16_t) 0x8000;                      \
      crc <<= 1;                                          \
      if ((u & v) != 0)                                   \
        crc++;                                            \
      if (xnz != 0)                                       \
        crc ^= (uint16_t) 0x1021;                         \
      v >>= 1;                                            \
      }                                                   \
    }                                                     \
  for (k = 0; k < 16; k++) {                              \
    if ((crc & (uint16_t) 0x8000) != 0)                   \
        crc = crc << 1 ^ (uint16_t) 0x1021;               \
      else                                                \
        crc <<= 1;                                        \
    }                                                     \
  *((pcrc) + 0) = (uint8_t) (crc >> 8 & (uint16_t) 0xff); \
  *((pcrc) + 1) = (uint8_t) (crc      & (uint16_t) 0xff); \
  }

/****************************************************************************/

#if (SYSTEM_CLOCK_BY_MEGA > 25)
#define                                                         \
macEarlySetupItemClockSetup                                     \
                                                                \
  /* For the following, see also                                \
     section 10. Prefetch Engine,                               \
     section 12.1. Programming The Flash Memory,                \
     and section 12.3. Security Options in C8051F34x.           \
     Prefetch engine takes two clock cycles for each read. */   \
  mysfr8_FLSCL = MSFR8_FOSE | (1) * MSFR8_FLRT;                 \
                                                                \
  /* Clock supplied to USB0 comes from 4x Clock Multiplier / 1, \
     System clock comes from 4x Clock Multiplier / 1. */        \
  mysfr8_CLKSEL = (0) * MSFR8_USBCLK2                           \
                | (0) * MSFR8_USBCLK1                           \
                | (0) * MSFR8_USBCLK0                           \
                | (0) * MSFR8_CLKSL2                            \
                | (1) * MSFR8_CLKSL1                            \
                | (1) * MSFR8_CLKSL0;

#else
#define                                                         \
macEarlySetupItemClockSetup                                     \
                                                                \
  /* For the following, see also                                \
     section 10. Prefetch Engine,                               \
     section 12.1. Programming The Flash Memory,                \
     and section 12.3. Security Options in C8051F34x.           \
     Prefetch engine takes one clock cycle for each read. */    \
  mysfr8_FLSCL = MSFR8_FOSE | (0) * MSFR8_FLRT;                 \
                                                                \
  /* Clock supplied to USB0 comes from 4x Clock Multiplier / 1, \
     System clock comes from 4x Clock Multiplier / 2. */        \
  mysfr8_CLKSEL = (0) * MSFR8_USBCLK2                           \
                | (0) * MSFR8_USBCLK1                           \
                | (0) * MSFR8_USBCLK0                           \
                | (0) * MSFR8_CLKSL2                            \
                | (1) * MSFR8_CLKSL1                            \
                | (0) * MSFR8_CLKSL0;

#endif

/****************************************************************************/

#define                      \
macEnterIdleMode             \
{                            \
  mysfr8_PCON |= MSFR8_IDLE; \
  }

/****************************************************************************/

#define                                                        \
macGetRandomBytesBase(mhzstate)                                \
{                                                              \
  uint32_t mydataloc u32;                                      \
                                                               \
  /* Totally scruffy, but fast and sufficiently noisy.         \
     Do not implement busy-waiting based code here. */         \
  *((mhzstate) + 0) = mysfr8_TMR2L;                            \
  *((mhzstate) + 1) = mysfr8_TMR2H;                            \
  u32 = timerstateaugmentation[0];                             \
  *((mhzstate) + 2) = (uint8_t) (u32       & (uint32_t) 0xff); \
  *((mhzstate) + 3) = (uint8_t) (u32 >>  8 & (uint32_t) 0xff); \
  *((mhzstate) + 4) = (uint8_t) (u32 >> 16 & (uint32_t) 0xff); \
  *((mhzstate) + 5) = (uint8_t) (u32 >> 24 & (uint32_t) 0xff); \
  u32 = timerstateaugmentation[1];                             \
  *((mhzstate) + 6) = (uint8_t) (u32       & (uint32_t) 0xff); \
  *((mhzstate) + 7) = (uint8_t) (u32 >>  8 & (uint32_t) 0xff); \
  *((mhzstate) + 8) = (uint8_t) (u32 >> 16 & (uint32_t) 0xff); \
  *((mhzstate) + 9) = (uint8_t) (u32 >> 24 & (uint32_t) 0xff); \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                          \
macGetUint16FromFifoUnused(fifo, val)            \
{                                                \
  uint8_t mydataloc fifoaux, lo, hi;             \
  uint16_t mydataloc valaux;                     \
                                                 \
  fifoaux = (fifo);                              \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);       \
  mysfr8_USB0ADR = fifoaux | MSFR8_USB0BUSY;     \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);       \
  lo = mysfr8_USB0DAT;                           \
  mysfr8_USB0ADR = fifoaux | MSFR8_USB0BUSY;     \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);       \
  hi = mysfr8_USB0DAT;                           \
  valaux = (uint16_t) (hi & (uint8_t) 0xff) << 8 \
         | (uint16_t) (lo & (uint8_t) 0xff);     \
  (val) = valaux;                                \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                                           \
macGetUint8ArrayFromFifo(fifo, cnt, buf)                          \
{                                                                 \
  uint8_t mydataloc fifoaux;                                      \
  uint16_t mydataloc cntaux;                                      \
  volatile uint8_t mydataloc * mydataloc bufaux;                  \
                                                                  \
  fifoaux = (fifo);                                               \
  cntaux = (cnt);                                                 \
  bufaux = (buf);                                                 \
  if (cntaux != 0) {                                              \
    while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                      \
    if (cntaux == 1) {                                            \
        mysfr8_USB0ADR = fifoaux | MSFR8_USB0BUSY;                \
        while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                  \
        *bufaux = mysfr8_USB0DAT;                                 \
        }                                                         \
      else {                                                      \
        mysfr8_USB0ADR = fifoaux | MSFR8_USB0BUSY | MSFR8_AUTORD; \
        while (--cntaux) {                                        \
          while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                \
          *bufaux++ = mysfr8_USB0DAT;                             \
          }                                                       \
        while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                  \
        mysfr8_USB0ADR = fifoaux;                                 \
        *bufaux = mysfr8_USB0DAT;                                 \
        }                                                         \
    }                                                             \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                     \
macGetUint8FromFifoUnused(fifo, val)        \
{                                           \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);  \
  mysfr8_USB0ADR = (fifo) | MSFR8_USB0BUSY; \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);  \
  (val) = mysfr8_USB0DAT;                   \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                         \
macGetUint8FromIndexedUsbReg(indx, usbreg, val) \
{                                               \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);      \
  mysfr8_USB0ADR = CUSB8_INDEX;                 \
  mysfr8_USB0DAT = (indx) & MUSB8_EPSEL;        \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);      \
  mysfr8_USB0ADR = (usbreg) | MSFR8_USB0BUSY;   \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);      \
  (val) = mysfr8_USB0DAT;                       \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                       \
macGetUint8FromUsbReg(usbreg, val)            \
{                                             \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);    \
  mysfr8_USB0ADR = (usbreg) | MSFR8_USB0BUSY; \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);    \
  (val) = mysfr8_USB0DAT;                     \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                                       \
macPutUint16ToFifoUnused(fifo, val)                           \
{                                                             \
  uint16_t mydataloc valaux;                                  \
                                                              \
  valaux = (val);                                             \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                    \
  mysfr8_USB0ADR = (fifo);                                    \
  mysfr8_USB0DAT = (uint8_t) (valaux & (uint16_t) 0xff);      \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                    \
  mysfr8_USB0DAT = (uint8_t) (valaux >> 8 & (uint16_t) 0xff); \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                                \
macPutUint8ArrayToFifo(fifo, cnt, buf)                 \
{                                                      \
  uint16_t mydataloc cntaux;                           \
  const volatile uint8_t mydataloc * mydataloc bufaux; \
                                                       \
  cntaux = (cnt);                                      \
  bufaux = (buf);                                      \
  if (cntaux != 0) {                                   \
    while (mysfr8_USB0ADR & MSFR8_USB0BUSY);           \
    mysfr8_USB0ADR = (fifo);                           \
    mysfr8_USB0DAT = *bufaux++;                        \
    while (--cntaux) {                                 \
      while (mysfr8_USB0ADR & MSFR8_USB0BUSY);         \
      mysfr8_USB0DAT = *bufaux++;                      \
      }                                                \
    }                                                  \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                        \
macPutUint8CodeArrayToFifo(fifo, cnt, buf)     \
{                                              \
  uint16_t mydataloc cntaux;                   \
  const uint8_t mycodeloc * mydataloc bufaux;  \
                                               \
  cntaux = (cnt);                              \
  bufaux = (buf);                              \
  if (cntaux != 0) {                           \
    while (mysfr8_USB0ADR & MSFR8_USB0BUSY);   \
    mysfr8_USB0ADR = (fifo);                   \
    mysfr8_USB0DAT = *bufaux++;                \
    while (--cntaux) {                         \
      while (mysfr8_USB0ADR & MSFR8_USB0BUSY); \
      mysfr8_USB0DAT = *bufaux++;              \
      }                                        \
    }                                          \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                    \
macPutUint8ToFifoUnused(fifo, val)         \
{                                          \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY); \
  mysfr8_USB0ADR = (fifo);                 \
  mysfr8_USB0DAT = (val);                  \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                       \
macPutUint8ToIndexedUsbReg(indx, usbreg, val) \
{                                             \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);    \
  mysfr8_USB0ADR = CUSB8_INDEX;               \
  mysfr8_USB0DAT = (indx) & MUSB8_EPSEL;      \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY);    \
  mysfr8_USB0ADR = (usbreg);                  \
  mysfr8_USB0DAT = (val);                     \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                    \
macPutUint8ToUsbReg(usbreg, val)           \
{                                          \
  while (mysfr8_USB0ADR & MSFR8_USB0BUSY); \
  mysfr8_USB0ADR = (usbreg);               \
  mysfr8_USB0DAT = (val);                  \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                        \
macPutZeroArrayToFifo(fifo, cnt)               \
{                                              \
  uint16_t mydataloc cntaux;                   \
                                               \
  cntaux = (cnt);                              \
  if (cntaux != 0) {                           \
    while (mysfr8_USB0ADR & MSFR8_USB0BUSY);   \
    mysfr8_USB0ADR = (fifo);                   \
    mysfr8_USB0DAT = 0;                        \
    while (--cntaux) {                         \
      while (mysfr8_USB0ADR & MSFR8_USB0BUSY); \
      mysfr8_USB0DAT = 0;                      \
      }                                        \
    }                                          \
  }

/****************************************************************************/

/* Conforms to information given under SFR Definition 16.2. USB0ADR and
   to the procedure description found under SFR Definition 16.3. USB0DAT. */
#define                                                           \
macRemoveUint8ArrayFromFifo(fifo, cnt)                            \
{                                                                 \
  uint8_t mydataloc fifoaux;                                      \
  uint16_t mydataloc cntaux;                                      \
  volatile uint8_t mydataloc bitbucket;                           \
                                                                  \
  fifoaux = (fifo);                                               \
  cntaux = (cnt);                                                 \
  if (cntaux != 0) {                                              \
    while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                      \
    if (cntaux == 1) {                                            \
        mysfr8_USB0ADR = fifoaux | MSFR8_USB0BUSY;                \
        while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                  \
        bitbucket = mysfr8_USB0DAT;                               \
        }                                                         \
      else {                                                      \
        mysfr8_USB0ADR = fifoaux | MSFR8_USB0BUSY | MSFR8_AUTORD; \
        while (--cntaux) {                                        \
          while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                \
          bitbucket = mysfr8_USB0DAT;                             \
          }                                                       \
        while (mysfr8_USB0ADR & MSFR8_USB0BUSY);                  \
        mysfr8_USB0ADR = fifoaux;                                 \
        bitbucket = mysfr8_USB0DAT;                               \
        }                                                         \
    bitbucket = *&bitbucket;                                      \
    }                                                             \
  }

/****************************************************************************/

#define                                       \
macSwitchLedOnOff(led, on, tmp)               \
{                                             \
  /* LEDs between PORT and GND. */            \
  (tmp) = (on) != 0 ? 1 : 0;                  \
  switch ((led)) {                            \
    case 1: { mysfr1_P0DOT0 = (tmp); break; } \
    case 2: { mysfr1_P0DOT1 = (tmp); break; } \
    case 3: { mysfr1_P0DOT2 = (tmp); break; } \
    }                                         \
  }

/****************************************************************************/

#define                                                    \
macMacDisableClockRecovery                                 \
{                                                          \
  macPutUint8ToUsbReg (CUSB8_CLKREC, 0x09 /* 000-01001 */) \
  }

/****************************************************************************/

#define                                                                      \
macMacEarlySetup                                                             \
{                                                                            \
  volatile uint8_t mydataloc cnt;                                            \
  uint8_t mydataloc tmp;                                                     \
                                                                             \
  /* Disable all interrupts. */                                              \
  mysfr1_EA = 0;                                                             \
                                                                             \
  /* Disable the watchdog timer, make PCA0MD modifiable. */                  \
  mysfr8_PCA0MD = 0;                                                         \
                                                                             \
  /* Disable most of the reset sources.                                      \
     Remember, Software Reset is always enabled. */                          \
  mysfr8_RSTSRC = 0;                                                         \
                                                                             \
  /* Disable the USB0 physical layer transceiver.                            \
     Enable the Pull-up Resistor and set the speed to Full Speed.            \
     So we are visible but we seem to be dead, in accordance to some         \
     recommendation that the clock should be active before the transceiver   \
     is enabled. */                                                          \
  mysfr8_USB0XCN = MSFR8_PREN | (0) * MSFR8_PHYEN | MSFR8_SPEED;             \
                                                                             \
  /* Voltage Regulator when operating the device in bus-powered mode. */     \
  mysfr8_REG0CN = 0;                                                         \
                                                                             \
  /* Enable IRQs generated by VBUS level sense. */                           \
  mysfr8_EIE2 = MSFR8_EVBUS;                                                 \
                                                                             \
  /* Set IRQs generated by VBUS level sense to high priority. */             \
  mysfr8_EIP2 = MSFR8_PVBUS;                                                 \
                                                                             \
  /* Turn the VDD monitor circuit on. */                                     \
  mysfr8_VDM0CN = MSFR8_VDMEN;                                               \
  /* Wait for a sufficiently high voltage value. */                          \
  while ((mysfr8_VDM0CN & MSFR8_VDDSTAT) == 0);                              \
                                                                             \
  /* The current 4x Clock Multiplier state is considered to be unknown.      \
     Temporarily bypass the 4x Clock Multiplier to avoid trouble,            \
     making sure that the clocks do not get lost.                            \
     So, clock supplied to USB0 will come from Internal Oscillator / 2, and  \
     system clock will come from Internal Oscillator divided by a factor as  \
     determined by the bits `OSCICN.IFCN1' and `OSCICN.IFCN0', i.e., the     \
     resulting system clock will be between 1.5 and 12 MHz, depending on     \
     the history. */                                                         \
  mysfr8_CLKSEL = (0) * MSFR8_USBCLK2                                        \
                | (0) * MSFR8_USBCLK1                                        \
                | (1) * MSFR8_USBCLK0                                        \
                | (0) * MSFR8_CLKSL2                                         \
                | (0) * MSFR8_CLKSL1                                         \
                | (0) * MSFR8_CLKSL0;                                        \
                                                                             \
  /* Enable the Internal H-F Oscillator in a way we like.                    \
     The resulting clock supplied to USB0 will be 6 MHz,                     \
     the resulting system clock will be 12 MHz. */                           \
  mysfr8_OSCICN = MSFR8_IOSCEN | MSFR8_IFCN1 | MSFR8_IFCN0;                  \
  /* Wait until the Internal H-F Oscillator                                  \
     is running at the programmed frequency. */                              \
  while ((mysfr8_OSCICN & MSFR8_IFRDY) == 0);                                \
                                                                             \
  /* The 4x Clock Multiplier is bypassed now. Perform the procedure in       \
     accordance with section 14.4. 4x Clock Multiplier in C8051F34x.         \
     Pay attention, Clock Recovery must be enabled for the following         \
     configuration with the internal oscillator (MULSEL = 00). */            \
  mysfr8_CLKMUL = 0;              /* Reset the Multiplier.                */ \
  mysfr8_CLKMUL = MSFR8_MULEN;    /* Enable the Multiplier.               */ \
  for (cnt = 0; cnt < 60; cnt++); /* Delay for more than 5 us (@ 12 MHz). */ \
  mysfr8_CLKMUL = MSFR8_MULEN                                                \
                | MSFR8_MULINIT;  /* Initialize the Multiplier.           */ \
  /* Wait until the Multiplier is locked. */                                 \
  while ((mysfr8_CLKMUL & MSFR8_MULRDY) == 0);                               \
                                                                             \
  /* The 4x Clock Multiplier setup finished.                                 \
     Perform the final clock setup. */                                       \
  macEarlySetupItemClockSetup                                                \
                                                                             \
  /* External Oscillator Control.                                            \
     Switch the External Oscillator circuit off. */                          \
  mysfr8_OSCXCN = 0;                                                         \
                                                                             \
  /* I/O port initialization.                                                \
     Question: Do we have LEDs at P0.0, P0.1, and P0.2 ? Yes ? Good. No ?    \
     Then we have to use a voltmeter to check our system clock setup. */     \
  mysfr8_P0      = 0xff;                                                     \
  mysfr8_P0MDIN  = 0xff;                                                     \
  mysfr8_P0MDOUT = (0) * 0x80 | (0) * 0x40 | (0) * 0x20 | (0) * 0x10         \
                 | (0) * 0x08 | (1) * 0x04 | (1) * 0x02 | (1) * 0x01;        \
  mysfr8_P0SKIP  = (1) * 0x80 | (1) * 0x40 | (1) * 0x20 | (1) * 0x10         \
                 | (1) * 0x08 | (0) * 0x04 | (0) * 0x02 | (0) * 0x01;        \
                                                                             \
  /* Enable the Crossbar, disabling things we do not need. */                \
  mysfr8_XBR1 = MSFR8_XBARE;                                                 \
                                                                             \
  /* Switch the LEDs off. */                                                 \
  macSwitchLedOnOff (1, 0, tmp)                                              \
  macSwitchLedOnOff (2, 0, tmp)                                              \
  macSwitchLedOnOff (3, 0, tmp)                                              \
  }

/****************************************************************************/

#define                                                                \
macMacEnableClockRecovery                                              \
{                                                                      \
  macPutUint8ToUsbReg (CUSB8_CLKREC, MUSB8_CRE | 0x09 /* 000-01001 */) \
  }

/****************************************************************************/

#define                                                          \
macMacSetEp12ToHaltedOrRunning(ep1, ep2, running)                \
{                                                                \
  uint8_t mydataloc bitstoset;                                   \
                                                                 \
  if ((ep1) != 0) {                                              \
    macPutUint8ToUsbReg (CUSB8_INDEX, 1)                         \
    if ((running) != 0) {                                        \
        ep12.haltstate1 = ep12haltstateRunning;                  \
        /* The idea is that things click into place more         \
           easily with MUSB8_FCDT at the beginning,              \
           or even not. */                                       \
        bitstoset =       MUSB8_DIRSEL /* EP Direction Select */ \
                  | (0) * MUSB8_FCDT;  /* Force Data Toggle   */ \
        macPutUint8ToUsbReg (CUSB8_EINCSRH, bitstoset)           \
        bitstoset = MUSB8_INCLRDT;     /* Clear Data Toggle   */ \
        macPutUint8ToUsbReg (CUSB8_EINCSRL, bitstoset)           \
        }                                                        \
      else {                                                     \
        ep12.haltstate1 = ep12haltstateHalted;                   \
        bitstoset = MUSB8_INCLRDT;     /* Clear Data Toggle   */ \
        macPutUint8ToUsbReg (CUSB8_EINCSRL, bitstoset)           \
        }                                                        \
    macPutUint8ToUsbReg (CUSB8_INDEX, 0)                         \
    }                                                            \
  if ((ep2) != 0) {                                              \
    macPutUint8ToUsbReg (CUSB8_INDEX, 2)                         \
    if ((running) != 0) {                                        \
        ep12.haltstate2 = ep12haltstateRunning;                  \
        ep12.dim       = dimcombuf;                              \
        ep12.cntk1     = 0;                                      \
        ep12.cntk2     = 0;                                      \
        ep12.buf3[0]   = 0;                                      \
        ep12.buf3[1]   = 0;                                      \
        ep12.buf3[2]   = 0;                                      \
        ep12.opc       = 0;                                      \
        ep12.buf0      = &combuf[0];                             \
        ep12.bufk      = &combuf[0];                             \
        ep12.commstate = ep12commstateIdle;                      \
        *(ep12.buf0 + 0) = 0;                                    \
        *(ep12.buf0 + 1) = 0;                                    \
        protocolstate = 0x80;                                    \
        if (numbercrunchingrequestedorperforming != 0)           \
          numbercruncherbufferprobablydestroyed = 1;             \
        bitstoset = MUSB8_OUTCLRDT; /* Clear Data Toggle */      \
        macPutUint8ToUsbReg (CUSB8_EOUTCSRL, bitstoset)          \
        }                                                        \
      else {                                                     \
        ep12.haltstate2 = ep12haltstateHalted;                   \
        bitstoset = MUSB8_OUTCLRDT; /* Clear Data Toggle */      \
        macPutUint8ToUsbReg (CUSB8_EOUTCSRL, bitstoset)          \
        }                                                        \
    macPutUint8ToUsbReg (CUSB8_INDEX, 0)                         \
    }                                                            \
  }

/****************************************************************************/

#define                                                                      \
macMacShipAnEp1Packet(firstpacket)                                           \
{                                                                            \
  uint16_t mydataloc cnt;                                                    \
  uint8_t mydataloc bitstoset;                                               \
                                                                             \
  /* Keep in mind, if `main()' is the caller here, then the interrupt        \
     handler `usbProcessEp1InInterrupt()' cannot interfere with the code     \
     flow. The interrupt handler `usbProcessEp0Interrupt()' could, but       \
     does not. */                                                            \
  if (ep12.haltstate1 != ep12haltstateHalted) {                              \
    if ((firstpacket) != 0) {                                                \
      /* Pay attention, the cruncher stores in big endian mode. */           \
      cnt = (uint16_t) (*(ep12.buf0 + 0) & (uint8_t) 0xff) << 8              \
          | (uint16_t) (*(ep12.buf0 + 1) & (uint8_t) 0xff);                  \
      ep12.cntk1 = cnt;                                                      \
      ep12.bufk  = ep12.buf0;                                                \
      ep12.commstate = ep12commstateWaitingForShipping;                      \
      }                                                                      \
    macGetUint8FromIndexedUsbReg (1, CUSB8_EINCSRL, ep0.eincsrl)             \
    if ((ep0.eincsrl & MUSB8_ININPRDY) == 0) {                               \
      cnt = ep12.cntk1;                                                      \
      if (cnt > USB_MAX_PACKET_LENGTH_EP1)                                   \
        cnt = USB_MAX_PACKET_LENGTH_EP1;                                     \
      if (cnt != 0)                                                          \
        macPutUint8ArrayToFifo (CUSB8_FIFO1, cnt, ep12.bufk)                 \
      ep12.cntk1 -= cnt;                                                     \
      ep12.bufk  += cnt;                                                     \
      /* Respect the `libusb' comments regarding the prevention              \
         of bulk/interrupt transfer overflows, that is for example,          \
         do not send short non-zero length packets via EP1. */               \
      if (cnt != 0 && cnt != USB_MAX_PACKET_LENGTH_EP1)                      \
        macPutZeroArrayToFifo (CUSB8_FIFO1, USB_MAX_PACKET_LENGTH_EP1 - cnt) \
      if (cnt == 0)                                                          \
        ep12.commstate = ep12commstateIdle;                                  \
      bitstoset = MUSB8_ININPRDY; /* IN Packet Ready */                      \
      macPutUint8ToUsbReg (CUSB8_EINCSRL, bitstoset)                         \
      }                                                                      \
    macPutUint8ToUsbReg (CUSB8_INDEX, 0)                                     \
    }                                                                        \
  }

/****************************************************************************/

#define                                        \
macMacMacAbort                                 \
{                                              \
  uint8_t mydataloc tmp;                       \
                                               \
  mysfr1_EA = 0; /* Disable all interrupts. */ \
  macSwitchLedOnOff (1, 0, tmp)                \
  macSwitchLedOnOff (2, 1, tmp)                \
  macSwitchLedOnOff (3, 0, tmp)                \
  macMacDisableClockRecovery                   \
  mysfr8_USB0XCN = 0;                          \
  for (;;)                                     \
    macEnterIdleMode                           \
  }

/****************************************************************************/

#define                                                                  \
macMacMacGeneralSetup(inittimstat, resetusb, initdevstat)                \
{                                                                        \
  /* The early setup is smart enough to be invoked here once more. */    \
  macMacEarlySetup                                                       \
                                                                         \
  /* Conditionally initialize some timer state. */                       \
  if ((inittimstat) != 0)                                                \
    timerstateaugmentation[0] = timerstateaugmentation[1] = 0;           \
                                                                         \
  /* Timer 2. */                                                         \
  mysfr8_TMR2RLL = timer2reload[0];                                      \
  mysfr8_TMR2RLH = timer2reload[1];                                      \
  mysfr1_TF2LEN  = 0; /* Timer 2 low byte interrupts disabled.        */ \
  mysfr1_T2CE    = 0; /* Timer 2 capture function disabled.           */ \
  mysfr1_T2SPLIT = 0; /* Timer 2 operates in 16-bit auto-reload mode. */ \
  mysfr1_TR2     = 1; /* Timer 2 enabled.                             */ \
  mysfr1_ET2     = 1; /* Enable IRQs generated by TF2L or TF2H.       */ \
  mysfr1_PT2     = 1; /* Timer 2 interrupts set to high priority.     */ \
  mysfr8_CKCON   = MSFR8_T2ML; /* Timer 2 low byte uses SYSCLK.       */ \
                                                                         \
  /* Conditionally generate an asynchronous USB0 reset.                  \
     All USB registers are reset to their default values following       \
     this asynchronous reset and the bit `POWER.USBINH' is set to `1'    \
     by hardware such that all USB traffic is ignored. */                \
  if ((resetusb) != 0)                                                   \
    macPutUint8ToUsbReg (CUSB8_POWER, MUSB8_USBRST)                      \
                                                                         \
  /* Define EP1 as IN EP. Power-On Reset value is OUT EP. */             \
  macPutUint8ToIndexedUsbReg (1, CUSB8_EINCSRH, MUSB8_DIRSEL)            \
  macPutUint8ToUsbReg (CUSB8_INDEX, 0)                                   \
                                                                         \
  /* Conditionally perform more device setup. */                         \
  if ((initdevstat) != 0) {                                              \
    devstate = devStateDefault;                                          \
    ep0.state = ep0stateIdle;                                            \
    macMacSetEp12ToHaltedOrRunning (1, 1, 0)                             \
    }                                                                    \
                                                                         \
  /* Enable IRQs generated by USB0. */                                   \
  mysfr8_EIE1 = MSFR8_EUSB0;                                             \
                                                                         \
  /* Configure the USB0 IN EP Interrupts. */                             \
  macPutUint8ToUsbReg (CUSB8_IN1IE, MUSB8_IN1E | MUSB8_EP0E)             \
                                                                         \
  /* Configure the USB0 OUT EP Interrupts. */                            \
  macPutUint8ToUsbReg (CUSB8_OUT1IE, MUSB8_OUT2E)                        \
                                                                         \
  /* Configure the USB0 Common Interrupts. */                            \
  macPutUint8ToUsbReg (CUSB8_CMIE, (0) * MUSB8_SOFE    /* SOF.     */ |  \
                                   (1) * MUSB8_RSTINTE /* Reset.   */ |  \
                                   (1) * MUSB8_RSUINTE /* Resume.  */ |  \
                                   (1) * MUSB8_SUSINTE /* Suspend. */ )  \
                                                                         \
  /* Transceiver Control.                                                \
     As seen, we follow the procedure described at the end of            \
     section 16.7. Function Configuration and Control in C8051F34x.      \
     Enable the Pull-up Resistor, enable the USB0 physical layer         \
     transceiver, and set the speed to Full Speed. */                    \
  mysfr8_USB0XCN = MSFR8_PREN | (1) * MSFR8_PHYEN | MSFR8_SPEED;         \
                                                                         \
  /* Switch on Clock Recovery. Pay attention.                            \
     The USB clock is active and the USB transceiver is enabled. */      \
  macMacEnableClockRecovery                                              \
                                                                         \
  /* Enable reset sources. In some cases, we should not mix the things.  \
     So, either IRQ or reset source, not both. */                        \
  mysfr8_RSTSRC = (0) * MSFR8_USBRSF /* USB resets.             */       \
                | (1) * MSFR8_MCDRSF /* Missing Clock Detector. */       \
                | (1) * MSFR8_PORSF; /* VDD monitor.            */       \
                                                                         \
  /* Make USB0 ready to work, unconditionally clearing `POWER.USBINH'.   \
     Enable Suspend Detection. */                                        \
  macPutUint8ToUsbReg (CUSB8_POWER, (1) * MUSB8_SUSEN)                   \
                                                                         \
  /* Enable all interrupts. */                                           \
  mysfr1_EA = 1;                                                         \
  }

/****************************************************************************/

#define                                                                 \
macMacMacGeneralSuspendBase                                             \
{                                                                       \
  /* Disable most of the reset sources.                                 \
     Remember, Software Reset is always enabled. */                     \
  mysfr8_RSTSRC = 0;                                                    \
                                                                        \
  /* Disable all Crossbar Port drivers. */                              \
  mysfr8_XBR1 = 0;                                                      \
                                                                        \
  /* Turn the VDD monitor circuit off. */                               \
  mysfr8_VDM0CN = 0;                                                    \
                                                                        \
  /* Disable Clock Recovery because USB will no longer be available. */ \
  macMacDisableClockRecovery                                            \
                                                                        \
  /* Put the transceiver into suspend mode. */                          \
  mysfr8_USB0XCN = MSFR8_PREN | (0) * MSFR8_PHYEN | MSFR8_SPEED;        \
                                                                        \
  /* Put the Voltage Regulator into low power mode. */                  \
  mysfr8_REG0CN = MSFR8_REGMOD;                                         \
  }

/****************************************************************************/

#if (defined (__C51__))
void SiLabs_Startup (void);
#elif (defined (_XC51_VER))
void _init_chip (void);
void _init_chip1 (void);
#else
#endif

#if (defined (__C51__))
extern void main (void);
#elif (defined (_XC51_VER))
extern void main (void);
#else
extern int main (void);
#endif

#if (defined (__C51__) || defined (_XC51_VER))
extern void cruncher (uint8_t mydataloc *);
#else
extern void fmc_a_mucoemu (uint8_t, uint8_t mydataloc *);
#endif

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
extern void ifaceabort (void);
extern void ifacebusywaitingformilliseconds (uint32_t);
extern const uint8_t mycodeloc * ifaceflashmemorylastlegaladdress (void);
extern const uint8_t mycodeloc *
  ifaceflashmemorypageaddress (const uint8_t mycodeloc *);
extern uint16_t ifaceflashmemorypagedim (void);
extern void ifaceflashmemorypageread (const uint8_t mycodeloc *,
  uint8_t mydataloc *);
extern void ifaceflashmemorypagewrite (const uint8_t mydataloc *,
  const uint8_t mycodeloc *);
extern void ifacegetappidandsernoloc (const uint8_t mycodeloc * mydataloc *,
  const uint8_t mycodeloc * mydataloc *, uint16_t mydataloc *,
  uint16_t mydataloc *);
extern uint16_t ifacegetbcddevicereleasenumber (void);
extern const uint8_t mycodeloc * const mycodeloc *
  ifacegetconstaddrarrayaddress (uint8_t);
extern const uint16_t mycodeloc * ifacegetconstlengarrayaddress (uint8_t);
extern void ifacegetrandombytesbase (uint8_t mydataloc *);
#endif

/****************************************************************************/

static void topCrc16 (uint16_t, uint8_t mydataloc *, uint8_t mydataloc *);
static void topGeneralSetupMain (uint8_t, uint8_t, uint8_t);
static void topGeneralSetupUsb (uint8_t, uint8_t, uint8_t);
static void topGeneralSuspendUsb (void);
static void topGeneralSuspendVbusLevel (void);
#if (defined (__C51__))
extern void topInterruptHandlerTimer2 (void);
extern void topInterruptHandlerUsb (void);
extern void topInterruptHandlerVbusLevel (void);
#elif (defined (_XC51_VER))
extern void ISR_PARAMS_TIMER2 topInterruptHandlerTimer2 (void);
extern void ISR_PARAMS_USB topInterruptHandlerUsb (void);
extern void ISR_PARAMS_VBUSLEVEL topInterruptHandlerVbusLevel (void);
#else
extern void topInterruptHandlerTimer2 (void);
extern void topInterruptHandlerUsb (void);
extern void topInterruptHandlerVbusLevel (void);
#endif
static uint8_t topMemCmpVol (const volatile void mydataloc *,
  const volatile void mydataloc *, uint16_t);
static void topMemCpyVol (volatile void mydataloc *,
  const volatile void mydataloc *, uint16_t);
static void topShipAnEp1Packet (uint8_t);

/****************************************************************************/

#if (0)
static void usbCrc16 (uint16_t, uint8_t mydataloc *, uint8_t mydataloc *);
#endif
static void usbProcessEp0Interrupt (void);
static void usbProcessEp1InInterrupt (void);
static void usbProcessEp2OutInterrupt (void);
static void usbReqEpi (const uint8_t mycodeloc *,
  volatile uint8_t mydataloc *, uint16_t, uint16_t, uint16_t, uint16_t);
static void usbRequestReceptionErrorHandling (void);

/****************************************************************************/

static void reqInpStd (void);
static void reqInpStdGetCon (void);
static void reqInpStdGetDes (void);
static void reqInpStdGetDesCon (void);
static void reqInpStdGetDesDev (void);
static void reqInpStdGetDesDqu (void);
static void reqInpStdGetDesEpt (void);
static void reqInpStdGetDesHid (void);
static void reqInpStdGetDesIfp (void);
static void reqInpStdGetDesInt (void);
static void reqInpStdGetDesOsc (void);
static void reqInpStdGetDesRep (void);
static void reqInpStdGetDesStr (void);
static void reqInpStdGetInt (void);
static void reqInpStdGetSta (void);
static void reqInpStdSynFra (void);
static void reqOutStd (void);
static void reqOutStdClrFea (void);
static void reqOutStdSetAdr (void);
static void reqOutStdSetCon (void);
static void reqOutStdSetDes (void);
static void reqOutStdSetDesCon (void);
static void reqOutStdSetDesDev (void);
static void reqOutStdSetDesDqu (void);
static void reqOutStdSetDesEpt (void);
static void reqOutStdSetDesHid (void);
static void reqOutStdSetDesIfp (void);
static void reqOutStdSetDesInt (void);
static void reqOutStdSetDesOsc (void);
static void reqOutStdSetDesRep (void);
static void reqOutStdSetDesStr (void);
static void reqOutStdSetFea (void);
static void reqOutStdSetInt (void);
static void reqInpCls (void);
static void reqInpClsGetIdl (void);
static void reqInpClsGetPro (void);
static void reqInpClsGetRep (void);
static void reqOutCls (void);
static void reqOutClsSetIdl (void);
static void reqOutClsSetPro (void);
static void reqOutClsSetRep (void);
static void reqInpVen (void);
static void reqInpVenGetBsi (void);
static void reqInpVenGetCi0 (void);
static void reqInpVenGetCi1 (void);
static void reqInpVenGetCo0 (void);
static void reqInpVenGetDsi (void);
static void reqInpVenGetHai (void);
static void reqInpVenGetHrd (void);
static void reqOutVen (void);
static void reqOutVenSetDp1 (void);
static void reqOutVenSetDp2 (void);
static void reqOutVenSetGf0 (void);
static void reqOutVenSetGf1 (void);
static void reqOutVenSetHlt (void);
static void reqOutVenSetRun (void);
static void reqOutVenSetTia (void);
static void reqOutVenSetTim (void);

/****************************************************************************/

static void lowAbort (void);
#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
static void lowFlashMemoryWriteByte (volatile uint8_t mydatalocfast *,
  volatile uint8_t mydataloc *);
#endif
static void lowGetRandomBytesBase (volatile uint8_t mydataloc *);
static void lowGetUint8ArrayFromFifo (uint8_t, uint16_t,
  volatile uint8_t mydataloc *);
static uint8_t lowGetUint8FromIndexedUsbReg (uint8_t, uint8_t);
static uint8_t lowGetUint8FromUsbReg (uint8_t);
static const usbtwostringdescriptor_t mycodeloc * lowGetUsbStrAdr (uint8_t);
static const uint8_t mycodeloc * lowGetUsbStrAsChrAdr (uint8_t);
static uint16_t lowGetUsbStrLen (uint8_t);
static void lowMemCpyVol (volatile void mydataloc *,
  const volatile void mydataloc *, uint16_t);
static void lowPutUint8ArrayToFifo (uint8_t, uint16_t,
  const volatile uint8_t mydataloc *);
static void lowPutUint8CodeArrayToFifo (uint8_t, uint16_t,
  const uint8_t mycodeloc *);
static void lowPutUint8ToIndexedUsbReg (uint8_t, uint8_t, uint8_t);
static void lowPutUint8ToUsbReg (uint8_t, uint8_t);
static void lowPutZeroArrayToFifo (uint8_t, uint16_t);
static void lowRemoveUint8ArrayFromFifo (uint8_t, uint16_t);
static void lowSetEp12ToHaltedOrRunning (uint8_t, uint8_t, uint8_t);
static void lowShipAnEp1Packet (uint8_t);

/****************************************************************************/

#if (defined (c_plusplus) || defined (__cplusplus))
}
#endif

/****************************************************************************/

#if (defined (__C51__))
void SiLabs_Startup (void)
{
  macMacEarlySetup
  return;
  }
#elif (defined (_XC51_VER))
void _init_chip (void)
{
  macMacEarlySetup
  return;
  }
#else
#endif

/****************************************************************************/

#if (defined (__C51__))
#elif (defined (_XC51_VER))
void _init_chip1 (void)
{
  return;
  }
#else
#endif

/****************************************************************************/

#if (defined (__C51__))
void
#elif (defined (_XC51_VER))
void
#else
int
#endif
main (void)
{
  uint16_t mydataloc cnt;
  uint8_t mydataloc rc;

  /* Initialize the cruncher state. */
  numbercrunchingrequestedorperforming = 0;
  numbercruncherbufferprobablydestroyed = 0;
  /* Setup the device.
     Force an asynchronous USB0 reset.
     Initialize the variables. */
  (void) topGeneralSetupMain (1, 1, 1);
  for (;;) {
    if (numbercrunchingrequestedorperforming != 0) {
#if (defined (__C51__) || defined (_XC51_VER))
      (void) cruncher (ep12latch.buf0);
#else
      (void) fmc_a_mucoemu (0, ep12latch.buf0);
#endif
      if (topMemCmpVol (&ep12latch, &ep12, (uint16_t) sizeof (ep12)) != 0)
        numbercruncherbufferprobablydestroyed = 1;
      /* Pay attention, the cruncher stores in big endian mode. */
      cnt = (uint16_t) (*(ep12latch.buf0 + 0) & (uint8_t) 0xff) << 8
          | (uint16_t) (*(ep12latch.buf0 + 1) & (uint8_t) 0xff);
      /* Make sure the cruncher output is sendable. */
      if (numbercruncherbufferprobablydestroyed) {
          (void) topMemCpyVol (&ep12, &ep12latch, (uint16_t) sizeof (ep12));
          rc = MUCO_RC_CONTROLBLOCKDESTROYED;
          }
        else if (cnt < 3 || cnt > ep12.dim) {
          rc = MUCO_RC_UNRECOVERABLEPROBLEM;
          }
        else {
          rc = MUCO_RC_SUCCESS;
          }
      if (rc != MUCO_RC_SUCCESS) {
        /* Make the cruncher output sendable. */
        *(ep12.buf0 + 0) = 0;
        *(ep12.buf0 + 1) = 8;
        *(ep12.buf0 + 2) = rc;
        (void) topCrc16 (3, ep12.buf0 + 0, ep12.buf0 + 3);
        *(ep12.buf0 + 5) = *(ep12.buf0 + 3) ^ *(ep12.buf0 + 4);
        (void) topCrc16 (6, ep12.buf0 + 0, ep12.buf0 + 6);
        }
      if (ep0.useep0insteadofep1 == 0)
        if (ep0.manuallytriggeredep1shipping == 0)
          (void) topShipAnEp1Packet (1);
      numbercrunchingrequestedorperforming = 0;
      }
    macEnterIdleMode
    }
  /* Never reached. */
#if (defined (__C51__))
  return;
#elif (defined (_XC51_VER))
  return;
#else
  return (0);
#endif
  }

/****************************************************************************/

#if (defined (IMPLEMENT_A_CRUNCHER_STUB))
void
#if (defined (__C51__) || defined (_XC51_VER))
cruncher (uint8_t mydataloc *p)
#else
fmc_a_mucoemu (uint8_t slot8, uint8_t mydataloc *p)
#endif
{
  uint8_t mydataloc crc16char [2];
  uint8_t mydataloc gothelo;

#if (defined (__C51__) || defined (_XC51_VER))
#else
  slot8 = *&slot8;
#endif
#if (!defined (EXCLUDE_IFACES))
  if (p == 0) {
    /* Fool compiler and linker. Never reached, but this
       discovers every single call from an illegal context.
       Pay attention, we are not going to implement
       reentrant functions here. */
    (void) ifaceabort ();
    (void) ifacebusywaitingformilliseconds (0);
    (void) ifaceflashmemorylastlegaladdress ();
    (void) ifaceflashmemorypageaddress (0);
    (void) ifaceflashmemorypagedim ();
    (void) ifaceflashmemorypageread (0, 0);
    (void) ifaceflashmemorypagewrite (0, 0);
    (void) ifacegetappidandsernoloc (0, 0, 0, 0);
    (void) ifacegetbcddevicereleasenumber ();
    (void) ifacegetconstaddrarrayaddress (0);
    (void) ifacegetconstlengarrayaddress (0);
    (void) ifacegetrandombytesbase (0);
    }
#endif
  gothelo = 0;
  if (*(p + 0) ==  0 &&
      *(p + 1) == 10 &&
      *(p + 2) == MUCO_OPC_HELO) {
    if (*(p + 3) == 'H' &&
        *(p + 4) == 'E' &&
        *(p + 5) == 'L' &&
        *(p + 6) == 'O') {
      if (*(p + 7) == '1' ||
          *(p + 7) == '2' ||
          *(p + 7) == '3') {
        (void) topCrc16 (10, p + 0, &crc16char[0]);
        if (crc16char[0] == 0 &&
            crc16char[1] == 0) {
          gothelo = 1;
          }
        }
      }
    }
  if (gothelo != 0) {
    /* Incomplete but tolerated cruncher response. */
    *(p +  0) = 0;
    *(p +  1) = 15;
    *(p +  2) = 0;
    *(p +  3) = 0;
    *(p +  4) = 0;
    *(p +  5) = 0;
    *(p +  6) = 0;
    *(p +  7) = 0;
    *(p +  8) = 0;
    *(p +  9) = 0;
    *(p + 10) = 0;
    (void) topCrc16 ( 8, p + 3, p + 11);
    (void) topCrc16 (13, p + 0, p + 13);
    return;
    }
  /* For the remainder change one byte for debugging and return. */
  *(p + 2) = 0;
  return;
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
void
ifaceabort (void)
{
  macMacMacAbort
  return;
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
void
ifacebusywaitingformilliseconds (uint32_t milliseconds)
{
  volatile uint32_t mydataloc u1, v0, v1, s1, t0, t1;
  uint32_t mydataloc a0, a1, a2, a3;

  u1 = timerstateaugmentation[1];
  v0 = timerstateaugmentation[0];
  v1 = timerstateaugmentation[1];
  while (v1 != u1) {
    u1 = v1;
    v0 = timerstateaugmentation[0];
    v1 = timerstateaugmentation[1];
    }
  for (;;) {
    s1 = timerstateaugmentation[1];
    t0 = timerstateaugmentation[0];
    t1 = timerstateaugmentation[1];
    while (t1 != s1) {
      s1 = t1;
      t0 = timerstateaugmentation[0];
      t1 = timerstateaugmentation[1];
      }
    /* 64-bit subtraction. */
    a0 = (t0       & (uint32_t) 0xffff) + (uint32_t) 0x10000;
    a1 = (t0 >> 16 & (uint32_t) 0xffff) + (uint32_t) 0x0ffff;
    a2 = (t1       & (uint32_t) 0xffff) + (uint32_t) 0x0ffff;
    a3 = (t1 >> 16 & (uint32_t) 0xffff) + (uint32_t) 0x0ffff;
    a0 -= v0       & (uint32_t) 0xffff;
    a1 -= v0 >> 16 & (uint32_t) 0xffff;
    a2 -= v1       & (uint32_t) 0xffff;
    a3 -= v1 >> 16 & (uint32_t) 0xffff;
    a1 += a0 >> 16;
    a2 += a1 >> 16;
    a3 += a2 >> 16;
    a0 &= (uint32_t) 0xffff;
    a1 &= (uint32_t) 0xffff;
    a2 &= (uint32_t) 0xffff;
    a3 &= (uint32_t) 0xffff;
    if ((a1 << 16 | a0) >= milliseconds || a2 != 0 || a3 != 0)
      break;
    }
  return;
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
const uint8_t mycodeloc *
ifaceflashmemorylastlegaladdress (void)
{
  return ( (const uint8_t mycodeloc *) 0 +
           (uint16_t) FLASH_MEMORY_LAST_LEGAL_ADDRESS );
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
const uint8_t mycodeloc *
ifaceflashmemorypageaddress (const uint8_t mycodeloc *p)
{
  static uint8_t mydataloc first = 1;
  static uint16_t mydataloc pagedim;
  static uint8_t mydataloc addressbyteorderislittleendian;
  union {
    uint8_t                 u8 [2];
    const uint8_t mycodeloc *p;
    } volatile mydataloc aux;
  uint16_t mydataloc u0, u1;
  uint8_t mydataloc b;

  if (first != 0) {
    first = 0;
    pagedim = ifaceflashmemorypagedim ();
    aux.p = p;
    /* Pay attention. On 8-bit architectures,
       a pointer and a 16-bit unsigned integer
       need not be of the same endianness.
       Take this into account when doing dirty things
       as we are going to do here. */
    u0 = ((uint16_t) aux.u8[0] & (uint16_t) 0xff) << 8
       | ((uint16_t) aux.u8[1] & (uint16_t) 0xff);
    aux.p = p == 0 ? p + 1 : p - 1;
    u1 = ((uint16_t) aux.u8[0] & (uint16_t) 0xff) << 8
       | ((uint16_t) aux.u8[1] & (uint16_t) 0xff);
    u0 = u1 > u0 ? u1 - u0 : u0 - u1;
    aux.u8[0] = (uint8_t) (u0 >> 8 & (uint16_t) 0xff);
    aux.u8[1] = (uint8_t) (u0      & (uint16_t) 0xff);
    if (aux.u8[0] == 0 && aux.u8[1] == 1)
        addressbyteorderislittleendian = 0;
      else if (aux.u8[0] == 1 && aux.u8[1] == 0)
        addressbyteorderislittleendian = 1;
      else
        /* Strange things happen here. */
        addressbyteorderislittleendian = 2;
    if (addressbyteorderislittleendian == 2)
      (void) ifaceabort ();
    }
  aux.p = p;
  if (addressbyteorderislittleendian) {
    b = aux.u8[0];
    aux.u8[0] = aux.u8[1];
    aux.u8[1] = b;
    }
  u0 = ((uint16_t) aux.u8[0] & (uint16_t) 0xff) << 8
     | ((uint16_t) aux.u8[1] & (uint16_t) 0xff);
  u0 = u0 - u0 % pagedim;
  aux.u8[0] = (uint8_t) (u0 >> 8 & (uint16_t) 0xff);
  aux.u8[1] = (uint8_t) (u0      & (uint16_t) 0xff);
  if (addressbyteorderislittleendian) {
    b = aux.u8[0];
    aux.u8[0] = aux.u8[1];
    aux.u8[1] = b;
    }
  if (aux.p > p || p >= aux.p + pagedim)
    (void) ifaceabort ();
  return (aux.p);
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
uint16_t
ifaceflashmemorypagedim (void)
{
  return ((uint16_t) FLASH_MEMORY_PAGE_SIZE);
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
void
ifaceflashmemorypageread (const uint8_t mycodeloc *f, uint8_t mydataloc *t)
{
  uint16_t mydataloc i;

  if (f != ifaceflashmemorypageaddress (f))
    (void) ifaceabort ();
  for (i = 0; i < ifaceflashmemorypagedim (); i++)
    *(t + i) = *(f + i);
  return;
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
void
ifaceflashmemorypagewrite (const uint8_t mydataloc *f,
                            const uint8_t mycodeloc *t)
{
  volatile uint8_t mydatalocfast params [5];
  volatile uint16_t mydataloc pagedim;
  union {
    volatile uint8_t mydataloc *td;
    const uint8_t mycodeloc    *tc;
    } volatile mydataloc aux;
  volatile uint8_t mydataloc * mydataloc td;
  volatile uint8_t mydataloc writeenable;
  uint16_t mydataloc i;

  pagedim = ifaceflashmemorypagedim ();
  if (t != ifaceflashmemorypageaddress (t))
    (void) ifaceabort ();
  aux.tc = t;
  td = aux.td;
  /* Each byte of a software flash write is written individually. */
  mysfr8_PFE0CN = (1) * MSFR8_PFEN | (0) * MSFR8_FLBWE;
  writeenable = MSFR8_PSWE;
  params[0] = MSFR8_PSEE | MSFR8_PSWE;
  params[1] = 0xa5;
  params[2] = 0xf1;
  params[3] = 0xff;
  params[4] = 0;
  /* Glance over the assembly language code to be sure that, inside
     the code section where the interrupts are disabled, no access
     happens to those program memory areas that contain constants.
     In short, inside that code section, there should not be seen
     a MOVC instruction. Now, temporarily disable all interrupts. */
  mysfr1_EA = 0;
  /* Erase the page.
     Pass the arguments to the following function in such a way
     that any access to the parameters inside the function
     does not cause the execution of a MOVX instruction. */
  (void) lowFlashMemoryWriteByte (&params[0], td);
  params[0] = writeenable;
  /* Refill the page. */
  for (i = 0; i < pagedim; i++) {
    params[3] = *(f + i);
    /* Pass the arguments to the following function in such a way
       that any access to the parameters inside the function
       does not cause the execution of a MOVX instruction. */
    (void) lowFlashMemoryWriteByte (&params[0], td + i);
    }
  /* Enable all interrupts. */
  mysfr1_EA = 1;
  return;
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
void
ifacegetappidandsernoloc (const uint8_t mycodeloc * mydataloc *ppa,
                           const uint8_t mycodeloc * mydataloc *pps,
                           uint16_t mydataloc *pla, uint16_t mydataloc *pls)
{
  *ppa = (const uint8_t mycodeloc *) &hiddenapplicationid;
  *pps = (const uint8_t mycodeloc *) &usbstringserialnumber;
  *pla = (uint16_t) (sizeof (hiddenapplicationid  ) / sizeof (uint8_t));
  *pls = (uint16_t) (sizeof (usbstringserialnumber) / sizeof (uint8_t));
  return;
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
uint16_t
ifacegetbcddevicereleasenumber (void)
{
  uint16_t mydataloc n;

  n = ((uint16_t) usbdevicedescriptor.bcdDevice_hi & (uint16_t) 0xff) << 8
    | ((uint16_t) usbdevicedescriptor.bcdDevice_lo & (uint16_t) 0xff);
  return (n);
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
const uint8_t mycodeloc * const mycodeloc *
ifacegetconstaddrarrayaddress (uint8_t updatelevel)
{
  static const uint8_t mycodeloc * const mycodeloc buf0 [] = {
    0
    };
  static const uint8_t mycodeloc * const mycodeloc buf1 [] = {
    (const uint8_t mycodeloc *) &usbstringserialnumber,
    (const uint8_t mycodeloc *) &hiddenapplicationid,
    0
    };
  static const uint8_t mycodeloc * const mycodeloc buf2 [] = {
    &usbdevicedescriptor.idVendor_lo,
    (const uint8_t mycodeloc *) &usbstringmanufacturer,
    (const uint8_t mycodeloc *) &usbstringproduct,
    (const uint8_t mycodeloc *) &usbstringserialnumber,
    (const uint8_t mycodeloc *) &usbstringconfiguration,
    (const uint8_t mycodeloc *) &usbstringinterface,
    (const uint8_t mycodeloc *) &hiddenapplicationid,
    0
    };
  static const uint8_t mycodeloc * const mycodeloc buf3 [] = {
    &usbdevicedescriptor.idVendor_lo,
    &tcd.usbconfigdescriptor.bMaxPower,
    (const uint8_t mycodeloc *) &usbstringmanufacturer,
    (const uint8_t mycodeloc *) &usbstringproduct,
    (const uint8_t mycodeloc *) &usbstringserialnumber,
    (const uint8_t mycodeloc *) &usbstringconfiguration,
    (const uint8_t mycodeloc *) &usbstringinterface,
    (const uint8_t mycodeloc *) &hiddenapplicationid,
    0
    };

  switch (updatelevel) {
    case 1: { return (&buf1[0]); }
    case 2: { return (&buf2[0]); }
    case 3: { return (&buf3[0]); }
    }
  return (&buf0[0]);
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
const uint16_t mycodeloc *
ifacegetconstlengarrayaddress (uint8_t updatelevel)
{
  static const uint16_t mycodeloc buf0 [] = {
    0
    };
  static const uint16_t mycodeloc buf1 [] = {
    (uint16_t) sizeof (usbstringserialnumber),
    (uint16_t) sizeof (hiddenapplicationid  ),
    0
    };
  static const uint16_t mycodeloc buf2 [] = {
    6,
    (uint16_t) sizeof (usbstringmanufacturer ),
    (uint16_t) sizeof (usbstringproduct      ),
    (uint16_t) sizeof (usbstringserialnumber ),
    (uint16_t) sizeof (usbstringconfiguration),
    (uint16_t) sizeof (usbstringinterface    ),
    (uint16_t) sizeof (hiddenapplicationid   ),
    0
    };
  static const uint16_t mycodeloc buf3 [] = {
    6,
    1,
    (uint16_t) sizeof (usbstringmanufacturer ),
    (uint16_t) sizeof (usbstringproduct      ),
    (uint16_t) sizeof (usbstringserialnumber ),
    (uint16_t) sizeof (usbstringconfiguration),
    (uint16_t) sizeof (usbstringinterface    ),
    (uint16_t) sizeof (hiddenapplicationid   ),
    0
    };

  switch (updatelevel) {
    case 1: { return (&buf1[0]); }
    case 2: { return (&buf2[0]); }
    case 3: { return (&buf3[0]); }
    }
  return (&buf0[0]);
  }
#endif

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
void
ifacegetrandombytesbase (uint8_t mydataloc *mhzstate)
{
  macGetRandomBytesBase (mhzstate)
  return;
  }
#endif

/****************************************************************************/

static void
topCrc16 (uint16_t n, uint8_t mydataloc *pbuf, uint8_t mydataloc *pcrc)
{
  macCrc16 (n, pbuf, pcrc)
  return;
  }

/****************************************************************************/

static void
topGeneralSetupMain (uint8_t inittimstat, uint8_t resetusb,
                      uint8_t initdevstat)
{
  macMacMacGeneralSetup (inittimstat, resetusb, initdevstat)
  return;
  }

/****************************************************************************/

static void
topGeneralSetupUsb (uint8_t inittimstat, uint8_t resetusb,
                     uint8_t initdevstat)
{
  macMacMacGeneralSetup (inittimstat, resetusb, initdevstat)
  return;
  }

/****************************************************************************/

static void
topGeneralSuspendUsb (void)
{
  macMacMacGeneralSuspendBase
  return;
  }

/****************************************************************************/

static void
topGeneralSuspendVbusLevel (void)
{
  macMacMacGeneralSuspendBase
  return;
  }

/****************************************************************************/

#define pwmactivetime  ((uint8_t ) (LED_PWM_ACTIVE_TIME_BY_MILLISECONDS ))
#define pwmtotalperiod ((uint8_t ) (LED_PWM_TOTAL_PERIOD_BY_MILLISECONDS))
#define rawperiodfast  ((uint16_t) (LED_BLINKING_PERIOD_BY_MILLISECONDS_FAST))
#define rawperiodslow  ((uint16_t) (LED_BLINKING_PERIOD_BY_MILLISECONDS_SLOW))
#define halfperiodfast ((uint16_t) ((rawperiodfast) >> 1))
#define halfperiodslow ((uint16_t) ((rawperiodslow) >> 1))

/****************************************************************************/

void
#if (defined (__C51__))
topInterruptHandlerTimer2 (void) ISR_PARAMS_TIMER2
#elif (defined (_XC51_VER))
ISR_PARAMS_TIMER2 topInterruptHandlerTimer2 (void)
#else
topInterruptHandlerTimer2 (void)
#endif
{
  static uint16_t mydataloc u16fast = 0;
  static uint16_t mydataloc u16slow = 0;
  static uint8_t mydataloc u8pwm = 0;
  static uint8_t mydataloc on1old = 0;
  static uint8_t mydataloc on2old = 0;
  uint8_t mydataloc onfast, onslow, on1, on2, tmp;

  if (mysfr1_TF2H) {
    mysfr1_TF2H = 0;
    if (timerstateaugmentation[0] != (uint32_t) 0xffffffff)
        timerstateaugmentation[0]++;
      else if (timerstateaugmentation[1] != (uint32_t) 0xffffffff) {
        timerstateaugmentation[1]++;
        timerstateaugmentation[0] = 0;
        }
      else {
        timerstateaugmentation[1] = 0;
        timerstateaugmentation[0] = 0;
        }
    u16fast++;
    u16slow++;
    if (u16fast > 2 * halfperiodfast - 1)
      u16fast = 0;
    if (u16slow > 2 * halfperiodslow - 1)
      u16slow = 0;
    onfast = u16fast < halfperiodfast ? 1 : 0;
    onslow = u16slow < halfperiodslow ? 1 : 0;
    on1 = numbercrunchingrequestedorperforming != 0 ? onfast : onslow;
    u8pwm++;
    if (u8pwm > pwmtotalperiod - 1)
      u8pwm = 0;
    on2 = u8pwm < pwmactivetime ? 1 : 0;
    if (on1old != on1 || on2old != on2) {
      on1old = on1;
      on2old = on2;
      macSwitchLedOnOff (1, on1 * on2, tmp)
      macSwitchLedOnOff (3, (1 - on1) * on2, tmp)
      }
    }
  return;
  }

/****************************************************************************/

#undef halfperiodslow
#undef halfperiodfast
#undef rawperiodslow
#undef rawperiodfast
#undef pwmtotalperiod
#undef pwmactivetime

/****************************************************************************/

void
#if (defined (__C51__))
topInterruptHandlerUsb (void) ISR_PARAMS_USB
#elif (defined (_XC51_VER))
ISR_PARAMS_USB topInterruptHandlerUsb (void)
#else
topInterruptHandlerUsb (void)
#endif
{
  ep0.cmint = lowGetUint8FromUsbReg (CUSB8_CMINT);
  ep0.in1int = lowGetUint8FromUsbReg (CUSB8_IN1INT);
  ep0.out1int = lowGetUint8FromUsbReg (CUSB8_OUT1INT);
  if (ep0.cmint & MUSB8_RSUINT) {
    /* Resume Interrupt-pending Flag was set.
       It has been cleared when software read the CMINT register. */
    (void) topGeneralSetupUsb (0, 0, 0);
    }
  if (ep0.cmint & MUSB8_RSTINT) {
    /* Reset Interrupt-pending Flag was set.
       It has been cleared when software read the CMINT register. */
    (void) topGeneralSetupUsb (1, 0, 1);
    }
  if (ep0.in1int & MUSB8_EP0) {
    /* Endpoint 0 Interrupt-pending Flag was set.
       It has been cleared when software read the IN1INT register. */
    (void) usbProcessEp0Interrupt ();
    }
  if (ep0.in1int & MUSB8_IN1) {
    /* IN Endpoint 1 Interrupt-pending Flag was set.
       It has been cleared when software read the IN1INT register. */
    (void) usbProcessEp1InInterrupt ();
    }
  if (ep0.out1int & MUSB8_OUT2) {
    /* OUT Endpoint 2 Interrupt-pending Flag was set.
       It has been cleared when software read the OUT1INT register. */
    (void) usbProcessEp2OutInterrupt ();
    }
  if (ep0.cmint & MUSB8_SUSINT) {
    /* Suspend Interrupt-pending Flag was set.
       It has been cleared when software read the CMINT register. */
    (void) topGeneralSuspendUsb ();
    /* Suspend the Internal H-F Oscillator. */
    mysfr8_OSCICN = MSFR8_IOSCEN | MSFR8_IFCN1 | MSFR8_IFCN0
                  | MSFR8_SUSPEND;
    }
  return;
  }

/****************************************************************************/

void
#if (defined (__C51__))
topInterruptHandlerVbusLevel (void) ISR_PARAMS_VBUSLEVEL
#elif (defined (_XC51_VER))
ISR_PARAMS_VBUSLEVEL topInterruptHandlerVbusLevel (void)
#else
topInterruptHandlerVbusLevel (void)
#endif
{
  /* Critical situation with regard to the power supply.
     Firstly, disable all interrupts.
     Shut the device down. */
  mysfr1_EA = 0;
  (void) topGeneralSuspendVbusLevel ();
  /* Put the CPU into Stop Mode. */
  mysfr8_PCON |= MSFR8_STOP;
  return;
  }

/****************************************************************************/

static uint8_t
topMemCmpVol (const volatile void mydataloc *p,
               const volatile void mydataloc *q, uint16_t n)
{
  uint16_t mydataloc i;

  for (i = 0; i < n; i++) {
    if (*((const volatile uint8_t mydataloc *) p + i) !=
        *((const volatile uint8_t mydataloc *) q + i))
      return (1);
    }
  return (0);
  }

/****************************************************************************/

static void
topMemCpyVol (volatile void mydataloc *p, const volatile void mydataloc *q,
               uint16_t n)
{
  uint16_t mydataloc i;

  for (i = 0; i < n; i++)
    *((      volatile uint8_t mydataloc *) p + i) =
    *((const volatile uint8_t mydataloc *) q + i);
  return;
  }

/****************************************************************************/

static void
topShipAnEp1Packet (uint8_t firstpacket)
{
  macMacShipAnEp1Packet (firstpacket)
  return;
  }

/****************************************************************************/

#if (0)
static void
usbCrc16 (uint16_t n, uint8_t mydataloc *pbuf, uint8_t mydataloc *pcrc)
{
  macCrc16 (n, pbuf, pcrc)
  return;
  }
#endif

/****************************************************************************/

static void
usbProcessEp0Interrupt (void)
{
  uint8_t mydataloc bitstoset;
  uint16_t mydataloc cnt;

  ep0.e0csr = lowGetUint8FromIndexedUsbReg (0, CUSB8_E0CSR);
  if (ep0.e0csr & MUSB8_STSTL) {
    /* This is for debugging. */
    if (ep0.cnt0ststl == 255)
        ep0.cnt0ststl = 0;
      else
        ep0.cnt0ststl++;
    }
  if (ep0.e0csr & MUSB8_SUEND) {
    /* Previous transfer ended due to a protocol violation. */
    ep0.state = ep0stateStalling;
    bitstoset = MUSB8_SSUEND | MUSB8_SDSTL;
    (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
    return;
    }
  if ((ep0.state != ep0stateIdle     ) &&
      (ep0.state != ep0stateReceiving) &&
      (ep0.e0csr & MUSB8_OPRDY)) {
    /* A previous transfer left the FIFO in an undefined state.
       Flush the FIFO. */
    ep0.state = ep0stateStalling;
    cnt = (uint16_t) lowGetUint8FromUsbReg (CUSB8_E0CNT);
    if (cnt != 0)
      (void) lowRemoveUint8ArrayFromFifo (CUSB8_FIFO0, cnt);
    bitstoset = MUSB8_SOPRDY | MUSB8_DATAEND | MUSB8_SDSTL;
    (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
    return;
    }
  if (ep0.e0csr & MUSB8_INPRDY) {
    /* A previous packet is waiting to be sent.
       Perform busy-waiting. */
    bitstoset = MUSB8_SDSTL;
    (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
    return;
    }
  if (ep0.state == ep0stateStalling) {
    /* We should be clean here. */
    ep0.state = ep0stateIdle;
    }
  if (ep0.state == ep0stateIdle) {
    if (ep0.e0csr & MUSB8_OPRDY) {
      cnt = (uint16_t) lowGetUint8FromUsbReg (CUSB8_E0CNT);
      if (cnt != 8) {
        /* There is a problem. */
        (void) usbRequestReceptionErrorHandling ();
        return;
        }
      (void) lowGetUint8ArrayFromFifo (CUSB8_FIFO0, 8, &ep0.bmRequestType);
      ep0.wValue  = (uint16_t) (ep0.wValue_hi  & (uint8_t) 0xff) << 8
                  | (uint16_t) (ep0.wValue_lo  & (uint8_t) 0xff);
      ep0.wIndex  = (uint16_t) (ep0.wIndex_hi  & (uint8_t) 0xff) << 8
                  | (uint16_t) (ep0.wIndex_lo  & (uint8_t) 0xff);
      ep0.wLength = (uint16_t) (ep0.wLength_hi & (uint8_t) 0xff) << 8
                  | (uint16_t) (ep0.wLength_lo & (uint8_t) 0xff);
      switch (ep0.bmRequestType & (uint8_t) 0x80 /* 1-00-000-00 */ ) {
        case 0x80 /* 1-00-000-00 */ : {
          switch (ep0.bmRequestType & (uint8_t) 0x60 /* 0-11-000-00 */ ) {
            case 0x00 /* 0-00-000-00 */ : { (void) reqInpStd (); return; }
            case 0x20 /* 0-01-000-00 */ : { (void) reqInpCls (); return; }
            case 0x40 /* 0-10-000-00 */ : { (void) reqInpVen (); return; }
            }
          (void) usbRequestReceptionErrorHandling ();
          return;
          }
        case 0x00 /* 0-00-000-00 */ : {
          switch (ep0.bmRequestType & (uint8_t) 0x60 /* 0-11-000-00 */ ) {
            case 0x00 /* 0-00-000-00 */ : { (void) reqOutStd (); return; }
            case 0x20 /* 0-01-000-00 */ : { (void) reqOutCls (); return; }
            case 0x40 /* 0-10-000-00 */ : { (void) reqOutVen (); return; }
            }
          (void) usbRequestReceptionErrorHandling ();
          return;
          }
        }
      (void) usbRequestReceptionErrorHandling ();
      return;
      }
    /* We are idle, but the SIE does not have a packet for us.
       The best is to return simply. */
    return;
    }
  if (ep0.state == ep0stateReceiving) {
    if (ep0.e0csr & MUSB8_OPRDY) {
      cnt = (uint16_t) lowGetUint8FromUsbReg (CUSB8_E0CNT);
      if (cnt > USB_MAX_PACKET_LENGTH_EP0 ||
          cnt > ep0.bytesfromhosttodiscard) {
        /* There is a problem.
           See also section 9.3.5 wLength in USB Spec Rev 2.0. */
        (void) usbRequestReceptionErrorHandling ();
        return;
        }
      if (cnt != 0)
        /* We will not allow data to be stored here. */
        (void) lowRemoveUint8ArrayFromFifo (CUSB8_FIFO0, cnt);
      ep0.bytesfromhosttodiscard -= cnt;
      bitstoset = MUSB8_SOPRDY;
      if (ep0.bytesfromhosttodiscard == 0) {
        ep0.state = ep0stateIdle;
        bitstoset |= MUSB8_DATAEND;
        }
      (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
      return;
      }
    /* We are in receive mode, but the SIE does not have a packet for us.
       The best is to return simply. */
    return;
    }
  if (ep0.state == ep0stateTransmitting) {
    if ((ep0.e0csr & (MUSB8_INPRDY | MUSB8_OPRDY | MUSB8_SUEND)) == 0) {
      /* There is no previous packet waiting to be sent, the FIFO is
         free, and the last control transaction ended properly. */
      if (ep0.bytesfromdevice != 0) {
        cnt = ep0.bytesfromdevice;
        if (cnt > USB_MAX_PACKET_LENGTH_EP0)
          cnt = USB_MAX_PACKET_LENGTH_EP0;
        if (cnt != 0) {
          if (ep0.pc != 0) {
              (void) lowPutUint8CodeArrayToFifo (CUSB8_FIFO0, cnt, ep0.pc);
              ep0.pc += cnt;
              }
            else {
              (void) lowPutUint8ArrayToFifo (CUSB8_FIFO0, cnt, ep0.pv);
              ep0.pv += cnt;
              }
          }
        ep0.bytesfromdevice -= cnt;
        bitstoset = MUSB8_INPRDY;
        if (ep0.bytesfromdevice == 0) {
          bitstoset |= MUSB8_DATAEND;
          ep0.state = ep0stateIdle;
          }
        (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
        return;
        }
      if (ep0.zerosfromdevice != 0) {
        cnt = ep0.zerosfromdevice;
        if (cnt > USB_MAX_PACKET_LENGTH_EP0)
          cnt = USB_MAX_PACKET_LENGTH_EP0;
        if (cnt != 0)
          (void) lowPutZeroArrayToFifo (CUSB8_FIFO0, cnt);
        ep0.zerosfromdevice -= cnt;
        bitstoset = MUSB8_INPRDY;
        if (ep0.zerosfromdevice == 0) {
          bitstoset |= MUSB8_DATAEND;
          ep0.state = ep0stateIdle;
          }
        (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
        return;
        }
      }
    }
  return;
  }

/****************************************************************************/

static void
usbProcessEp1InInterrupt (void)
{
  uint8_t mydataloc bitstoset;

  /* This is for debugging. */
  if (ep0.cntin1int == 255)
      ep0.cntin1int = 0;
    else
      ep0.cntin1int++;
  if (ep12.haltstate1 == ep12haltstateHalted) {
    /* Except for the Default Control Pipe, the Halt feature is required
       to be implemented for all interrupt and bulk endpoint types.
       See section 9.4.5 Get Status in USB Spec Rev 2.0. */
    bitstoset = MUSB8_INSDSTL; /* Send Stall. */
    (void) lowPutUint8ToIndexedUsbReg (1, CUSB8_EINCSRL, bitstoset);
    (void) lowPutUint8ToUsbReg (CUSB8_INDEX, 0);
    return;
    }
  if (numbercrunchingrequestedorperforming == 0) {
    if (ep12.commstate == ep12commstateWaitingForShipping) {
      /* A previous packet was successfully sent. So reset MUSB8_FCDT, if
         it was set. From now on, the EP1 data toggle bit switches only
         when an ACK is received following a data packet transmission. */
      bitstoset = MUSB8_DIRSEL; /* Endpoint Direction Select. */
      (void) lowPutUint8ToIndexedUsbReg (1, CUSB8_EINCSRH, bitstoset);
      (void) lowPutUint8ToUsbReg (CUSB8_INDEX, 0);
      /* And now send the current packet. */
      (void) lowShipAnEp1Packet (0);
      }
    }
  return;
  }

/****************************************************************************/

static void
usbProcessEp2OutInterrupt (void)
{
  uint8_t mydataloc bitstoset;
  uint16_t mydataloc cntfifo, cnt;

  if (ep12.haltstate2 == ep12haltstateHalted) {
    /* Except for the Default Control Pipe, the Halt feature is required
       to be implemented for all interrupt and bulk endpoint types.
       See section 9.4.5 Get Status in USB Spec Rev 2.0. */
    bitstoset = MUSB8_OUTSDSTL; /* Send Stall. */
    (void) lowPutUint8ToIndexedUsbReg (2, CUSB8_EOUTCSRL, bitstoset);
    (void) lowPutUint8ToUsbReg (CUSB8_INDEX, 0);
    return;
    }
  ep0.eoutcsrl = lowGetUint8FromIndexedUsbReg (2, CUSB8_EOUTCSRL);
  if (ep0.eoutcsrl & MUSB8_OUTOPRDY) {
    cntfifo = (uint16_t) (lowGetUint8FromUsbReg (CUSB8_EOUTCNTH) &
                          (uint8_t) 0x03) << 8
            | (uint16_t) (lowGetUint8FromUsbReg (CUSB8_EOUTCNTL) &
                          (uint8_t) 0xff);
    if (cntfifo != USB_MAX_PACKET_LENGTH_EP2) {
      /***** LABEL *****/ label_remove_unexpected_data:
      if (cntfifo != 0)
        (void) lowRemoveUint8ArrayFromFifo (CUSB8_FIFO2, cntfifo);
      bitstoset = 0;
      (void) lowPutUint8ToUsbReg (CUSB8_EOUTCSRL, bitstoset);
      (void) lowPutUint8ToUsbReg (CUSB8_INDEX, 0);
      return;
      }
    if (ep12.commstate == ep12commstateIdle) {
      (void) lowGetUint8ArrayFromFifo (CUSB8_FIFO2, 3, &ep12.buf3[0]);
      /* Pay attention, the cruncher reads in big endian mode. */
      ep12.cntk2 = (uint16_t) (ep12.buf3[0] & (uint8_t) 0xff) << 8
                 | (uint16_t) (ep12.buf3[1] & (uint8_t) 0xff);
      if (ep12.cntk2 < 3)
        ep12.cntk2 = 3;
      if (ep12.buf3[2] & (uint8_t) 0x80) {
          /* Use the larger buffer. */
          ep12.dim  = dimbytecode;
          ep12.buf0 = &bytecode[0];
          }
        else {
          /* Use the standard buffer. */
          ep12.dim  = dimcombuf;
          ep12.buf0 = &combuf[0];
          }
      if (ep12.cntk2 > ep12.dim)
        ep12.cntk2 = ep12.dim;
      *(ep12.buf0 + 0) = ep12.buf3[0];
      *(ep12.buf0 + 1) = ep12.buf3[1];
      *(ep12.buf0 + 2) = ep12.buf3[2];
      ep12.opc         = ep12.buf3[2];
      ep12.cntk2 -= 3;
      ep12.bufk = ep12.buf0 + 3;
      cntfifo -= 3;
      ep12.commstate = ep12commstateWaitingForReception;
      }
    if (ep12.commstate == ep12commstateWaitingForReception) {
      cnt = cntfifo;
      if (cnt > ep12.cntk2)
        cnt = ep12.cntk2;
      if (cnt != 0)
        (void) lowGetUint8ArrayFromFifo (CUSB8_FIFO2, cnt, ep12.bufk);
      ep12.cntk2 -= cnt;
      ep12.bufk  += cnt;
      if (cntfifo > cnt)
        (void) lowRemoveUint8ArrayFromFifo (CUSB8_FIFO2, cntfifo - cnt);
      if (ep12.cntk2 == 0) {
        ep12.commstate = ep12commstateCrunchingOrCrunched;
        (void) lowMemCpyVol (&ep12latch, &ep12, (uint16_t) sizeof (ep12));
        numbercruncherbufferprobablydestroyed = 0;
        numbercrunchingrequestedorperforming = 1;
        }
      bitstoset = 0;
      (void) lowPutUint8ToUsbReg (CUSB8_EOUTCSRL, bitstoset);
      (void) lowPutUint8ToUsbReg (CUSB8_INDEX, 0);
      return;
      }
    goto label_remove_unexpected_data;
    }
  (void) lowPutUint8ToUsbReg (CUSB8_INDEX, 0);
  return;
  }

/****************************************************************************/

static void
usbReqEpi (const uint8_t mycodeloc *pc, volatile uint8_t mydataloc *pv,
            uint16_t bytesinbuf, uint16_t bytesexpectedfromdevice,
            uint16_t zerosfromdevice, uint16_t bytesfromhosttodiscard)
{
  uint16_t mydataloc mymax, mysum, bytesfromdevice, cnt;
  uint8_t mydataloc bitstoset;

  if (bytesexpectedfromdevice != 0)
    if ((pc != 0 && pv != 0) || (pc == 0 && pv == 0))
      (void) lowAbort ();
  mymax = 0;
  if (mymax < bytesexpectedfromdevice)
    mymax = bytesexpectedfromdevice;
  if (mymax < zerosfromdevice)
    mymax = zerosfromdevice;
  if (mymax < bytesfromhosttodiscard)
    mymax = bytesfromhosttodiscard;
  mysum = bytesexpectedfromdevice + zerosfromdevice + bytesfromhosttodiscard;
  if (mysum != mymax)
    (void) lowAbort ();
  bytesfromdevice = bytesexpectedfromdevice;
  if (bytesfromdevice > bytesinbuf) {
    /* See also section 9.3.5 wLength in USB Spec Rev 2.0. */
    bytesfromdevice = bytesinbuf;
    }
  ep0.pc = pc;
  ep0.pv = pv;
  ep0.bytesfromdevice        = bytesfromdevice;
  ep0.zerosfromdevice        = zerosfromdevice;
  ep0.bytesfromhosttodiscard = bytesfromhosttodiscard;
  if (ep0.bytesfromdevice        == 0 &&
      ep0.zerosfromdevice        == 0 &&
      ep0.bytesfromhosttodiscard == 0) {
    ep0.state = ep0stateIdle;
    /* The need for the following DATAEND can only be deduced very indirectly
       from the manual C8051F34x. It has been found out by debugging. */
    bitstoset = MUSB8_SOPRDY | MUSB8_DATAEND;
    (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
    return;
    }
  if (ep0.bytesfromhosttodiscard != 0) {
    ep0.state = ep0stateReceiving;
    bitstoset = MUSB8_SOPRDY;
    (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
    return;
    }
  if (ep0.bytesfromdevice != 0 ||
      ep0.zerosfromdevice != 0) {
    ep0.state = ep0stateTransmitting;
    /* Do not move the following three lines of code.
       Otherwise you risk losing the responsiveness of EP0. */
    bitstoset = MUSB8_SOPRDY;
    (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
    ep0.e0csr = lowGetUint8FromUsbReg (CUSB8_E0CSR);
    if ((ep0.e0csr & (MUSB8_INPRDY | MUSB8_OPRDY | MUSB8_SUEND)) == 0) {
      /* There is no previous packet waiting to be sent, the FIFO is
         free, and the last control transaction ended properly. */
      if (ep0.bytesfromdevice != 0) {
        cnt = ep0.bytesfromdevice;
        if (cnt > USB_MAX_PACKET_LENGTH_EP0)
          cnt = USB_MAX_PACKET_LENGTH_EP0;
        if (cnt != 0) {
          if (ep0.pc != 0) {
              (void) lowPutUint8CodeArrayToFifo (CUSB8_FIFO0, cnt, ep0.pc);
              ep0.pc += cnt;
              }
            else {
              (void) lowPutUint8ArrayToFifo (CUSB8_FIFO0, cnt, ep0.pv);
              ep0.pv += cnt;
              }
          }
        ep0.bytesfromdevice -= cnt;
        bitstoset = MUSB8_INPRDY;
        if (ep0.bytesfromdevice == 0) {
          bitstoset |= MUSB8_DATAEND;
          ep0.state = ep0stateIdle;
          }
        (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
        return;
        }
      if (ep0.zerosfromdevice != 0) {
        cnt = ep0.zerosfromdevice;
        if (cnt > USB_MAX_PACKET_LENGTH_EP0)
          cnt = USB_MAX_PACKET_LENGTH_EP0;
        if (cnt != 0)
          (void) lowPutZeroArrayToFifo (CUSB8_FIFO0, cnt);
        ep0.zerosfromdevice -= cnt;
        bitstoset = MUSB8_INPRDY;
        if (ep0.zerosfromdevice == 0) {
          bitstoset |= MUSB8_DATAEND;
          ep0.state = ep0stateIdle;
          }
        (void) lowPutUint8ToUsbReg (CUSB8_E0CSR, bitstoset);
        return;
        }
      (void) lowAbort ();
      return;
      }
    return;
    }
  (void) lowAbort ();
  return;
  }

/****************************************************************************/

static void
usbRequestReceptionErrorHandling (void)
{
  uint8_t mydataloc bitstoset;

  ep0.state = ep0stateStalling;
  bitstoset = MUSB8_SOPRDY | MUSB8_DATAEND | MUSB8_SDSTL;
  (void) lowPutUint8ToIndexedUsbReg (0, CUSB8_E0CSR, bitstoset);
  return;
  }

/****************************************************************************/

#define REQ_STD_GET_STATUS        ( 0)
#define REQ_STD_CLEAR_FEATURE     ( 1)
#define REQ_STD_SET_FEATURE       ( 3)
#define REQ_STD_SET_ADDRESS       ( 5)
#define REQ_STD_GET_DESCRIPTOR    ( 6)
#define REQ_STD_SET_DESCRIPTOR    ( 7)
#define REQ_STD_GET_CONFIGURATION ( 8)
#define REQ_STD_SET_CONFIGURATION ( 9)
#define REQ_STD_GET_INTERFACE     (10)
#define REQ_STD_SET_INTERFACE     (11)
#define REQ_STD_SYNCH_FRAME       (12)

/****************************************************************************/

static void
reqInpStd (void)
{
  switch (ep0.bRequest) {
    case REQ_STD_GET_STATUS:        { (void) reqInpStdGetSta (); return; }
    case REQ_STD_GET_DESCRIPTOR:    { (void) reqInpStdGetDes (); return; }
    case REQ_STD_GET_CONFIGURATION: { (void) reqInpStdGetCon (); return; }
    case REQ_STD_GET_INTERFACE:     { (void) reqInpStdGetInt (); return; }
    case REQ_STD_SYNCH_FRAME:       { (void) reqInpStdSynFra (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetCon (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured) &&
      ep0.bmRequestType == 0x80        &&
      ep0.wValue == 0                  &&
      ep0.wIndex == 0                  &&
      ep0.wLength == 1) {
    ep0.buf[0] = devstate == devStateAddress
               ? 0
               : tcd.usbconfigdescriptor.bConfigurationValue;
    (void) usbReqEpi (0, &ep0.buf[0], 1, 1, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDes (void)
{
  switch (ep0.wValue_hi) {
    case DESCR_TYPE_DEVICE:          { (void) reqInpStdGetDesDev (); return; }
    case DESCR_TYPE_CONFIGURATION:   { (void) reqInpStdGetDesCon (); return; }
    case DESCR_TYPE_STRING:          { (void) reqInpStdGetDesStr (); return; }
    case DESCR_TYPE_INTERFACE:       { (void) reqInpStdGetDesInt (); return; }
    case DESCR_TYPE_ENDPOINT:        { (void) reqInpStdGetDesEpt (); return; }
    case DESCR_TYPE_DEVICEQUALIFIER: { (void) reqInpStdGetDesDqu (); return; }
    case DESCR_TYPE_OTHERSPEEDCONF:  { (void) reqInpStdGetDesOsc (); return; }
    case DESCR_TYPE_INTERFACEPOWER:  { (void) reqInpStdGetDesIfp (); return; }
    case DESCR_TYPE_HID:             { (void) reqInpStdGetDesHid (); return; }
    case DESCR_TYPE_REPORT:          { (void) reqInpStdGetDesRep (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesCon (void)
{
  if (ep0.bmRequestType == 0x80 &&
      ep0.wValue_lo == 0        &&
      ep0.wIndex == 0           &&
      ep0.wLength != 0) {
    (void) usbReqEpi ((const uint8_t mycodeloc *) &tcd, 0,
                       (uint16_t) sizeof (tcd_t), ep0.wLength, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesDev (void)
{
  if (ep0.bmRequestType == 0x80 &&
      ep0.wValue_lo == 0        &&
      ep0.wIndex == 0           &&
      ep0.wLength != 0) {
    (void) usbReqEpi ((const uint8_t mycodeloc *) &usbdevicedescriptor, 0,
                       (uint16_t) sizeof (usbdevicedescriptor_t), ep0.wLength,
                       0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesDqu (void)
{
  /* If a full-speed only device with a USB specification release number in
     the device descriptor equal to 0x0200 receives a GetDescriptor() request
     for a Device_Qualifier, it must respond with a request error. See also
     sections 9.6.2 Device_Qualifier in USB Spec Rev 2.0. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesEpt (void)
{
  /* An endpoint descriptor is always returned as part of the configuration
     information returned by a GetDescriptor(Configuration) request. An
     endpoint descriptor cannot be directly accessed with a GetDescriptor()
     or SetDescriptor() request. Hence, there is no implementation here.
     See also section 9.6.6 Endpoint in USB Spec Rev 2.0. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesHid (void)
{
  if (ep0.bmRequestType == 0x81                  &&
      ep0.wValue_lo == 0                         &&
      ep0.wIndex == 0 /* HID Interface Number */ &&
      ep0.wLength != 0) {
    (void) usbReqEpi ((const uint8_t mycodeloc *) &tcd.usbhiddescriptor, 0,
                       (uint16_t) sizeof (usbhiddescriptor_t), ep0.wLength,
                       0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesIfp (void)
{
  /* The Interface_Power descriptor is not supported here. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesInt (void)
{
  /* An interface descriptor is always returned as part of the configuration
     information returned by a GetDescriptor(Configuration) request. An
     Interface descriptor cannot be directly accessed with a GetDescriptor()
     or SetDescriptor() request. Hence, there is no implementation here.
     See also section 9.6.5 Interface in USB Spec Rev 2.0. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesOsc (void)
{
  /* If a full-speed only device with a USB specification release number in
     the device descriptor equal to 0x0200 receives a GetDescriptor() request
     for a Device_Qualifier, it must respond with a request error. The host
     must not make a request for an Other_Speed_Configuration descriptor
     unless it first successfully retrieves the Device_Qualifier descriptor.
     This here is just for the case that it nevertheless makes one. See also
     sections 9.6.2 Device_Qualifier and 9.6.4 Other_Speed_Configuration
     in USB Spec Rev 2.0. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesRep (void)
{
  if (ep0.bmRequestType == 0x81                  &&
      ep0.wValue_lo == 0                         &&
      ep0.wIndex == 0 /* HID Interface Number */ &&
      ep0.wLength != 0) {
    (void) usbReqEpi (&usbreportdescriptor[0], 0,
                       (uint16_t) sizeof (usbreportdescriptor), ep0.wLength,
                       0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetDesStr (void)
{
  /* We do not know what comes in here as Language ID. Is it a Language ID
     out of the string of the supported languages, or anyone ? Since the
     present device uses only ASCII characters in its string descriptors, the
     actual Language ID does not matter. Hence, Language ID information
     carried by `ep0.wIndex' is simply ignored here. */
  if (ep0.bmRequestType == 0x80              &&
      ep0.wValue_lo < numberofusbstrings - 2 &&
      ep0.wLength != 0) {
    (void) usbReqEpi (lowGetUsbStrAsChrAdr (ep0.wValue_lo), 0,
                       lowGetUsbStrLen (ep0.wValue_lo), ep0.wLength, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetInt (void)
{
  if (devstate == devStateConfigured  &&
      ep0.bmRequestType == 0x81       &&
      ep0.wValue == 0                 &&
      ep0.wIndex == 0 /* Interface */ &&
      ep0.wLength == 1) {
    ep0.buf[0] = 0; /* Alternate Setting */
    (void) usbReqEpi (0, &ep0.buf[0], 1, 1, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdGetSta (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured) &&
      ep0.bmRequestType == 0x80        &&
      ep0.wValue == 0                  &&
      ep0.wIndex == 0 /* Device */     &&
      ep0.wLength == 2) {
    ep0.buf[0] = ( tcd.usbconfigdescriptor.bmAttributes & (uint8_t) 0x20
                     ? (uint8_t) 0x02
                     : (uint8_t) 0x00 )  /* Remote Wakeup */
               | ( tcd.usbconfigdescriptor.bmAttributes & (uint8_t) 0x40
                     ? (uint8_t) 0x01
                     : (uint8_t) 0x00 ); /* Self Powered  */
    ep0.buf[1] = 0;
    (void) usbReqEpi (0, &ep0.buf[0], 2, 2, 0, 0);
    return;
    }
  if (devstate == devStateConfigured  &&
      ep0.bmRequestType == 0x81       &&
      ep0.wValue == 0                 &&
      ep0.wIndex == 0 /* Interface */ &&
      ep0.wLength == 2) {
    ep0.buf[0] = 0;
    ep0.buf[1] = 0;
    (void) usbReqEpi (0, &ep0.buf[0], 2, 2, 0, 0);
    return;
    }
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured)                &&
      ep0.bmRequestType == 0x82                       &&
      ep0.wValue == 0                                 &&
      (ep0.wIndex & (uint16_t) 0x000f) == 0 /* EP0 */ &&
      ep0.wLength == 2) {
    ep0.buf[0] = 0; /* Halt feature not implemented for EP0. */
    ep0.buf[1] = 0;
    (void) usbReqEpi (0, &ep0.buf[0], 2, 2, 0, 0);
    return;
    }
  if (devstate == devStateConfigured &&
      ep0.bmRequestType == 0x82      &&
      ep0.wValue == 0                &&
      ep0.wIndex == 0x81 /* EP1 */   &&
      ep0.wLength == 2) {
    ep0.buf[0] = ep12.haltstate1 == ep12haltstateHalted ? 1 : 0;
    ep0.buf[1] = 0;
    (void) usbReqEpi (0, &ep0.buf[0], 2, 2, 0, 0);
    return;
    }
  if (devstate == devStateConfigured &&
      ep0.bmRequestType == 0x82      &&
      ep0.wValue == 0                &&
      ep0.wIndex == 0x02 /* EP2 */   &&
      ep0.wLength == 2) {
    ep0.buf[0] = ep12.haltstate2 == ep12haltstateHalted ? 1 : 0;
    ep0.buf[1] = 0;
    (void) usbReqEpi (0, &ep0.buf[0], 2, 2, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpStdSynFra (void)
{
  /* Isochronous data transfers are not supported. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStd (void)
{
  switch (ep0.bRequest) {
    case REQ_STD_CLEAR_FEATURE:     { (void) reqOutStdClrFea (); return; }
    case REQ_STD_SET_FEATURE:       { (void) reqOutStdSetFea (); return; }
    case REQ_STD_SET_ADDRESS:       { (void) reqOutStdSetAdr (); return; }
    case REQ_STD_SET_DESCRIPTOR:    { (void) reqOutStdSetDes (); return; }
    case REQ_STD_SET_CONFIGURATION: { (void) reqOutStdSetCon (); return; }
    case REQ_STD_SET_INTERFACE:     { (void) reqOutStdSetInt (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdClrFea (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured)           &&
      ep0.bmRequestType == 0x00                  &&
      ep0.wValue == 1 /* DEVICE_REMOTE_WAKEUP */ &&
      ep0.wIndex == 0 /* Device               */ &&
      ep0.wLength == 0) {
    /* Clearing DEVICE_REMOTE_WAKEUP is accepted. */
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured)                          &&
      ep0.bmRequestType == 0x02                                 &&
      ep0.wValue == 0                       /* ENDPOINT_HALT */ &&
      (ep0.wIndex & (uint16_t) 0x000f) == 0 /* EP0           */ &&
      ep0.wLength == 0) {
    /* Clearing ENDPOINT_HALT is accepted. */
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  if (devstate == devStateConfigured             &&
      ep0.bmRequestType == 0x02                  &&
      ep0.wValue == 0     /* ENDPOINT_HALT */    &&
      (ep0.wIndex == 0x81 /* EP1           */ ||
       ep0.wIndex == 0x02 /* EP2           */)   &&
      ep0.wLength == 0) {
    if (ep0.wIndex == 0x81)
        (void) lowSetEp12ToHaltedOrRunning (1, 0, 1);
      else
        (void) lowSetEp12ToHaltedOrRunning (0, 1, 1);
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetAdr (void)
{
  if (devstate == devStateDefault &&
      ep0.bmRequestType == 0x00   &&
      ep0.wValue <= 127           &&
      ep0.wIndex == 0             &&
      ep0.wLength == 0) {
    if (ep0.wValue != 0) {
        /* The host assigns a unique address to the USB device,
           moving the device to the Address state.
           See also section 9.1.2 Bus Enumeration in USB Spec Rev 2.0. */
        devstate = devStateAddress;
        (void) lowPutUint8ToUsbReg (CUSB8_FADDR, ep0.wValue_lo);
        (void) usbReqEpi (0, 0, 0, 0, 0, 0);
        return;
        }
      else {
        /* Otherwise, the device remains in the Default state,
           this is not an error condition.
           See also section 9.4.6 Set Address in USB Spec Rev 2.0. */
        (void) usbReqEpi (0, 0, 0, 0, 0, 0);
        return;
        }
    }
  if (devstate == devStateAddress &&
      ep0.bmRequestType == 0x00   &&
      ep0.wValue <= 127           &&
      ep0.wIndex == 0             &&
      ep0.wLength == 0) {
    if (ep0.wValue == 0) {
        /* If the address specified is zero,
           then the device shall enter the Default state,
           nothing more.
           See also section 9.4.6 Set Address in USB Spec Rev 2.0. */
        devstate = devStateDefault;
        (void) usbReqEpi (0, 0, 0, 0, 0, 0);
        return;
        }
      else {
        /* Otherwise, the device remains in the Address state
           but uses the newly-specified address.
           See also section 9.4.6 Set Address in USB Spec Rev 2.0. */
        if (ep0.wValue_lo != (lowGetUint8FromUsbReg (CUSB8_FADDR) & 0x7f)) {
            (void) lowPutUint8ToUsbReg (CUSB8_FADDR, ep0.wValue_lo);
            (void) usbReqEpi (0, 0, 0, 0, 0, 0);
            return;
            }
          else {
            (void) usbReqEpi (0, 0, 0, 0, 0, 0);
            return;
            }
        }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetCon (void)
{
  if ((devstate == devStateAddress                                   ||
       devstate == devStateConfigured)                                  &&
      ep0.bmRequestType == 0x00                                         &&
      ep0.wValue_hi == 0                                                &&
      (ep0.wValue_lo == 0                                            ||
       ep0.wValue_lo == tcd.usbconfigdescriptor.bConfigurationValue)    &&
      ep0.wIndex == 0                                                   &&
      ep0.wLength == 0) {
    if (ep0.wValue_lo == 0) {
        devstate = devStateAddress;
        /* Question: Does entering the Address state here really imply
           that EP1 and EP2 need be put into the Halt state ? It seems
           to make sense because we give up the current configuration. */
        (void) lowSetEp12ToHaltedOrRunning (1, 1, 0);
        (void) usbReqEpi (0, 0, 0, 0, 0, 0);
        return;
        }
      else {
        /* For EPs using data toggle, regardless of whether an EP has the Halt
           feature set, a ClearFeature(ENDPOINT_HALT) request always results
           in the data toggle being reinitialized to DATA0. It is just too
           logical that the same applies here as well. Further. The Halt
           feature is reset to zero after either a SetConfiguration() or
           SetInterface() request even if the requested configuration or
           interface is the same as the current configuration or interface.
           See also section 9.4.5 Get Status in USB Spec Rev 2.0. */
        devstate = devStateConfigured;
        (void) lowSetEp12ToHaltedOrRunning (1, 1, 1);
        (void) usbReqEpi (0, 0, 0, 0, 0, 0);
        return;
        }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDes (void)
{
  switch (ep0.wValue_hi) {
    case DESCR_TYPE_DEVICE:          { (void) reqOutStdSetDesDev (); return; }
    case DESCR_TYPE_CONFIGURATION:   { (void) reqOutStdSetDesCon (); return; }
    case DESCR_TYPE_STRING:          { (void) reqOutStdSetDesStr (); return; }
    case DESCR_TYPE_INTERFACE:       { (void) reqOutStdSetDesInt (); return; }
    case DESCR_TYPE_ENDPOINT:        { (void) reqOutStdSetDesEpt (); return; }
    case DESCR_TYPE_DEVICEQUALIFIER: { (void) reqOutStdSetDesDqu (); return; }
    case DESCR_TYPE_OTHERSPEEDCONF:  { (void) reqOutStdSetDesOsc (); return; }
    case DESCR_TYPE_INTERFACEPOWER:  { (void) reqOutStdSetDesIfp (); return; }
    case DESCR_TYPE_HID:             { (void) reqOutStdSetDesHid (); return; }
    case DESCR_TYPE_REPORT:          { (void) reqOutStdSetDesRep (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesCon (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured) &&
      ep0.bmRequestType == 0x00        &&
      ep0.wValue_lo == 0               &&
      ep0.wIndex == 0                  &&
      (ep0.wLength == (uint16_t) sizeof (usbconfigdescriptor_t) ||
       ep0.wLength == (uint16_t) sizeof (tcd_t))) {
    /* Data to be received will be discarded. */
    (void) usbReqEpi (0, 0, 0, 0, 0, ep0.wLength);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesDev (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured) &&
      ep0.bmRequestType == 0x00        &&
      ep0.wValue_lo == 0               &&
      ep0.wIndex == 0                  &&
      ep0.wLength == (uint16_t) sizeof (usbdevicedescriptor_t)) {
    /* Data to be received will be discarded. */
    (void) usbReqEpi (0, 0, 0, 0, 0, ep0.wLength);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesDqu (void)
{
  /* The only allowed values for descriptor type are
     device, configuration, and string descriptor types.
     See also section 9.4.8 Set Descriptor in USB Spec Rev 2.0.
     But keep in mind, the document USB Spec Rev 2.0 does only speak
     for its own descriptor types, not for any descriptor types
     described in USB HID Ver 1.11. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesEpt (void)
{
  /* The only allowed values for descriptor type are
     device, configuration, and string descriptor types.
     See also section 9.4.8 Set Descriptor in USB Spec Rev 2.0.
     But keep in mind, the document USB Spec Rev 2.0 does only speak
     for its own descriptor types, not for any descriptor types
     described in USB HID Ver 1.11. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesHid (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured)           &&
      ep0.bmRequestType == 0x01                  &&
      ep0.wValue_lo == 0                         &&
      ep0.wIndex == 0 /* HID Interface Number */ &&
      ep0.wLength == (uint16_t) sizeof (usbhiddescriptor_t)) {
    /* Data to be received will be discarded. */
    (void) usbReqEpi (0, 0, 0, 0, 0, ep0.wLength);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesIfp (void)
{
  /* The only allowed values for descriptor type are
     device, configuration, and string descriptor types.
     See also section 9.4.8 Set Descriptor in USB Spec Rev 2.0.
     But keep in mind, the document USB Spec Rev 2.0 does only speak
     for its own descriptor types, not for any descriptor types
     described in USB HID Ver 1.11. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesInt (void)
{
  /* The only allowed values for descriptor type are
     device, configuration, and string descriptor types.
     See also section 9.4.8 Set Descriptor in USB Spec Rev 2.0.
     But keep in mind, the document USB Spec Rev 2.0 does only speak
     for its own descriptor types, not for any descriptor types
     described in USB HID Ver 1.11. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesOsc (void)
{
  /* The only allowed values for descriptor type are
     device, configuration, and string descriptor types.
     See also section 9.4.8 Set Descriptor in USB Spec Rev 2.0.
     But keep in mind, the document USB Spec Rev 2.0 does only speak
     for its own descriptor types, not for any descriptor types
     described in USB HID Ver 1.11. */
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesRep (void)
{
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured)           &&
      ep0.bmRequestType == 0x01                  &&
      ep0.wValue_lo == 0                         &&
      ep0.wIndex == 0 /* HID Interface Number */ &&
      ep0.wLength == (uint16_t) sizeof (usbreportdescriptor)) {
    /* Data to be received will be discarded. */
    (void) usbReqEpi (0, 0, 0, 0, 0, ep0.wLength);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetDesStr (void)
{
  /* We do not know what comes in here as Language ID. Is it a Language ID
     out of the string of the supported languages, or anyone ? Since the
     present device uses only ASCII characters in its string descriptors, the
     actual Language ID does not matter. Hence, Language ID information
     carried by `ep0.wIndex' is simply ignored here. */
  if ((devstate == devStateAddress ||
       devstate == devStateConfigured) &&
      ep0.bmRequestType == 0x00        &&
      ep0.wValue_lo < numberofusbstrings - 2) {
    if (ep0.wLength == lowGetUsbStrLen (ep0.wValue_lo)) {
      /* Data to be received will be discarded. */
      (void) usbReqEpi (0, 0, 0, 0, 0, ep0.wLength);
      return;
      }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetFea (void)
{
  if (devstate == devStateConfigured                   &&
      ep0.bmRequestType == 0x02                        &&
      ep0.wValue == 0        /* ENDPOINT_HALT    */    &&
      ep0.wIndex_hi == 0     /* no Test Selector */    &&
      (ep0.wIndex_lo == 0x81 /* EP1              */ ||
       ep0.wIndex_lo == 0x02 /* EP2              */)   &&
      ep0.wLength == 0) {
    if (ep0.wIndex_lo == 0x81)
        (void) lowSetEp12ToHaltedOrRunning (1, 0, 0);
      else
        (void) lowSetEp12ToHaltedOrRunning (0, 1, 0);
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutStdSetInt (void)
{
  if (devstate == devStateConfigured          &&
      ep0.bmRequestType == 0x01               &&
      ep0.wValue == 0 /* Alternate Setting */ &&
      ep0.wIndex == 0 /* Interface         */ &&
      ep0.wLength == 0) {
    /* Alternate Setting is accepted.
       For EPs using data toggle, regardless of whether an EP has the Halt
       feature set, a ClearFeature(ENDPOINT_HALT) request always results
       in the data toggle being reinitialized to DATA0. It is just too
       logical that the same applies here as well. Further. The Halt
       feature is reset to zero after either a SetConfiguration() or
       SetInterface() request even if the requested configuration or
       interface is the same as the current configuration or interface.
       See also section 9.4.5 Get Status in USB Spec Rev 2.0. */
    (void) lowSetEp12ToHaltedOrRunning (1, 1, 1);
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

#define REQ_CLS_GET_REPORT   ( 1)
#define REQ_CLS_GET_IDLE     ( 2)
#define REQ_CLS_GET_PROTOCOL ( 3)
#define REQ_CLS_SET_REPORT   ( 9)
#define REQ_CLS_SET_IDLE     (10)
#define REQ_CLS_SET_PROTOCOL (11)

/****************************************************************************/

static void
reqInpCls (void)
{
  switch (ep0.bRequest) {
    case REQ_CLS_GET_REPORT:   { (void) reqInpClsGetRep (); return; }
    case REQ_CLS_GET_IDLE:     { (void) reqInpClsGetIdl (); return; }
    case REQ_CLS_GET_PROTOCOL: { (void) reqInpClsGetPro (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpClsGetIdl (void)
{
  if (ep0.bmRequestType == 0xa1 /* 10100001     */ &&
      ep0.wValue_hi == 0                           &&
      ep0.wValue_lo == 0        /* no Report ID */ &&
      ep0.wIndex == 0           /* Interface    */ &&
      ep0.wLength == 1) {
    ep0.buf[0] = hidcurrentidlerate;
    (void) usbReqEpi (0, &ep0.buf[0], 1, 1, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpClsGetPro (void)
{
  if (ep0.bmRequestType == 0xa1 /* 10100001  */ &&
      ep0.wValue == 0                           &&
      ep0.wIndex == 0           /* Interface */ &&
      ep0.wLength == 1) {
    ep0.buf[0] = 1; /* Report Protocol. */
    (void) usbReqEpi (0, &ep0.buf[0], 1, 1, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpClsGetRep (void)
{
  /* This request is mandatory and must be supported by all devices.
     See section 7.2 Class-Specific Requests in USB HID Ver 1.11. */
  if (ep0.bmRequestType == 0xa1 /* 10100001     */ &&
      ep0.wValue_hi == 1        /* Input        */ &&
      ep0.wValue_lo == 0        /* no Report ID */ &&
      ep0.wIndex == 0           /* Interface    */ &&
      ep0.wLength == USB_MAX_PACKET_LENGTH_EP1) {
    (void) usbReqEpi (0, 0, 0, 0, ep0.wLength, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutCls (void)
{
  switch (ep0.bRequest) {
    case REQ_CLS_SET_REPORT:   { (void) reqOutClsSetRep (); return; }
    case REQ_CLS_SET_IDLE:     { (void) reqOutClsSetIdl (); return; }
    case REQ_CLS_SET_PROTOCOL: { (void) reqOutClsSetPro (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutClsSetIdl (void)
{
  if (ep0.bmRequestType == 0x21 /* 00100001     */ &&
      ep0.wValue_lo == 0        /* no Report ID */ &&
      ep0.wIndex == 0           /* Interface    */ &&
      ep0.wLength == 0) {
    hidcurrentidlerate = ep0.wValue_hi;
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutClsSetPro (void)
{
  if (ep0.bmRequestType == 0x21 /* 00100001        */ &&
      ep0.wValue == 1           /* Report Protocol */ &&
      ep0.wIndex == 0           /* Interface       */ &&
      ep0.wLength == 0) {
    /* Report Protocol is accepted. */
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutClsSetRep (void)
{
  if (ep0.bmRequestType == 0x21 /* 00100001     */    &&
      (ep0.wValue_hi == 2       /* Output       */ ||
       ep0.wValue_hi == 3       /* Feature      */)   &&
      ep0.wValue_lo == 0        /* no Report ID */    &&
      ep0.wIndex == 0           /* Interface    */    &&
      ep0.wLength == USB_MAX_PACKET_LENGTH_EP2) {
    /* Data to be received will be discarded. */
    (void) usbReqEpi (0, 0, 0, 0, 0, ep0.wLength);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

#define REQ_VEN_GET_BUFFERSIZEINFO    ( 1)
#define REQ_VEN_GET_CRUNCHERINFO0     ( 2)
#define REQ_VEN_GET_CRUNCHEROUTPUT0   ( 3)
#define REQ_VEN_GET_CRUNCHERINFO1     ( 4)
#define REQ_VEN_GET_DEVICESTATUSINFO  ( 5)
#define REQ_VEN_GET_HIDDENAPPID       ( 6)
#define REQ_VEN_GET_HIDDENRELEASEDATE ( 7)
#define REQ_VEN_SET_DEBUGPACKAGE1     (11)
#define REQ_VEN_SET_DEBUGPACKAGE2     (12)
#define REQ_VEN_SET_GETCOUTPUTFROM0   (14)
#define REQ_VEN_SET_GETCOUTPUTFROM1   (15)
#define REQ_VEN_SET_SETEP12TOHALTED   (16)
#define REQ_VEN_SET_SETEP12TORUNNING  (17)
#define REQ_VEN_SET_SETEP1TRIGGERAUT  (18)
#define REQ_VEN_SET_SETEP1TRIGGERMAN  (19)

/****************************************************************************/

static void
reqInpVen (void)
{
  switch (ep0.bRequest) {
    case REQ_VEN_GET_BUFFERSIZEINFO:    { (void) reqInpVenGetBsi (); return; }
    case REQ_VEN_GET_CRUNCHERINFO0:     { (void) reqInpVenGetCi0 (); return; }
    case REQ_VEN_GET_CRUNCHEROUTPUT0:   { (void) reqInpVenGetCo0 (); return; }
    case REQ_VEN_GET_CRUNCHERINFO1:     { (void) reqInpVenGetCi1 (); return; }
    case REQ_VEN_GET_DEVICESTATUSINFO:  { (void) reqInpVenGetDsi (); return; }
    case REQ_VEN_GET_HIDDENAPPID:       { (void) reqInpVenGetHai (); return; }
    case REQ_VEN_GET_HIDDENRELEASEDATE: { (void) reqInpVenGetHrd (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetBsi (void)
{
  if (ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 4) {
    ep0.buf[0] = (uint8_t) (dimcombuf        & (uint16_t) 0xff);
    ep0.buf[1] = (uint8_t) (dimcombuf   >> 8 & (uint16_t) 0xff);
    ep0.buf[2] = (uint8_t) (dimbytecode      & (uint16_t) 0xff);
    ep0.buf[3] = (uint8_t) (dimbytecode >> 8 & (uint16_t) 0xff);
    (void) usbReqEpi (0, &ep0.buf[0], 4, 4, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetCi0 (void)
{
  uint16_t mydataloc cnt;

  if (devstate == devStateConfigured           &&
      ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 5) {
    ep0.buf[0] = numbercrunchingrequestedorperforming;
    ep0.buf[1] = numbercruncherbufferprobablydestroyed;
    ep0.buf[4] = tcd.usbendpoint1descriptor.bInterval;
    if ( numbercrunchingrequestedorperforming  != 0 ||
         numbercruncherbufferprobablydestroyed != 0 ||
         ep12.commstate != ep12commstateCrunchingOrCrunched ) {
        ep0.buf[2] = 0;
        ep0.buf[3] = 0;
        (void) usbReqEpi (0, &ep0.buf[0], 5, 5, 0, 0);
        }
      else {
        /* Pay attention, the cruncher stores in big endian mode. */
        cnt = (uint16_t) (*(ep12.buf0 + 0) & (uint8_t) 0xff) << 8
            | (uint16_t) (*(ep12.buf0 + 1) & (uint8_t) 0xff);
        ep0.buf[2] = (uint8_t) (cnt      & (uint16_t) 0xff);
        ep0.buf[3] = (uint8_t) (cnt >> 8 & (uint16_t) 0xff);
        (void) usbReqEpi (0, &ep0.buf[0], 5, 5, 0, 0);
        }
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetCi1 (void)
{
  uint16_t mydataloc cnt, rem;

  if (devstate == devStateConfigured           &&
      ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 5) {
    ep0.buf[0] = numbercrunchingrequestedorperforming;
    ep0.buf[1] = numbercruncherbufferprobablydestroyed;
    ep0.buf[4] = tcd.usbendpoint1descriptor.bInterval;
    if ( numbercrunchingrequestedorperforming  != 0 ||
         numbercruncherbufferprobablydestroyed != 0 ||
         ep12.commstate != ep12commstateCrunchingOrCrunched ) {
        ep0.buf[2] = 0;
        ep0.buf[3] = 0;
        (void) usbReqEpi (0, &ep0.buf[0], 5, 5, 0, 0);
        }
      else {
        /* Pay attention, the cruncher stores in big endian mode. */
        cnt = (uint16_t) (*(ep12.buf0 + 0) & (uint8_t) 0xff) << 8
            | (uint16_t) (*(ep12.buf0 + 1) & (uint8_t) 0xff);
        /* Respect the `libusb' comments regarding the prevention
           of bulk/interrupt transfer overflows, that is for example,
           do not send short packets from EP1. */
        rem = cnt % USB_MAX_PACKET_LENGTH_EP1;
        if (rem != 0)
          cnt += USB_MAX_PACKET_LENGTH_EP1 - rem;
        ep0.buf[2] = (uint8_t) (cnt      & (uint16_t) 0xff);
        ep0.buf[3] = (uint8_t) (cnt >> 8 & (uint16_t) 0xff);
        (void) usbReqEpi (0, &ep0.buf[0], 5, 5, 0, 0);
        if (ep0.useep0insteadofep1 == 0)
          if (ep0.manuallytriggeredep1shipping != 0)
            (void) lowShipAnEp1Packet (1);
        }
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetCo0 (void)
{
  uint16_t mydataloc cnt;

  if (devstate == devStateConfigured           &&
      ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength > 1) {
    /* Some host software is not able to access the cruncher response via EP1.
       This kind of host software will access the cruncher response by means
       of this request using EP0. */
    if ( numbercrunchingrequestedorperforming  != 0 ||
         numbercruncherbufferprobablydestroyed != 0 ||
         ep12.commstate != ep12commstateCrunchingOrCrunched ) {
        ep0.buf[0] = 0;
        ep0.buf[1] = 0;
        (void) usbReqEpi (0, &ep0.buf[0], 2, ep0.wLength, 0, 0);
        return;
        }
      else {
        /* Pay attention, the cruncher stores in big endian mode. */
        cnt = (uint16_t) (*(ep12.buf0 + 0) & (uint8_t) 0xff) << 8
            | (uint16_t) (*(ep12.buf0 + 1) & (uint8_t) 0xff);
        ep12.commstate = ep12commstateIdle;
        (void) usbReqEpi (0, ep12.buf0, cnt, ep0.wLength, 0, 0);
        return;
        }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetDsi (void)
{
  if (ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength != 0) {
    ep0.buf[0] = securitylockbyte;
    ep0.buf[1] = remaininglevel12updates;
    ep0.buf[2] = updatekeyenable[0];
    ep0.buf[3] = updatekeyenable[1];
    ep0.buf[4] = updatekeyenable[2];
    ep0.buf[5] = timer2reload[0];
    ep0.buf[6] = timer2reload[1];
    (void) lowGetRandomBytesBase (&ep0.buf[7]);
    ep0.buf[17] = numbercrunchingrequestedorperforming;
    ep0.buf[18] = numbercruncherbufferprobablydestroyed;
    ep0.buf[19] = tcd.usbendpoint1descriptor.bInterval;
    ep0.buf[20] = protocolstate;
    switch (devstate) {
      case devStateDefault:    { ep0.buf[21] = 1; break; }
      case devStateAddress:    { ep0.buf[21] = 2; break; }
      case devStateConfigured: { ep0.buf[21] = 3; break; }
      default:                 { ep0.buf[21] = 4; break; }
      }
    switch (ep12.haltstate1) {
      case ep12haltstateHalted:  { ep0.buf[22] = 1; break; }
      case ep12haltstateRunning: { ep0.buf[22] = 2; break; }
      default:                   { ep0.buf[22] = 3; break; }
      }
    switch (ep12.haltstate2) {
      case ep12haltstateHalted:  { ep0.buf[23] = 1; break; }
      case ep12haltstateRunning: { ep0.buf[23] = 2; break; }
      default:                   { ep0.buf[23] = 3; break; }
      }
    switch (ep12.commstate) {
      case ep12commstateIdle:                { ep0.buf[24] = 1; break; }
      case ep12commstateWaitingForReception: { ep0.buf[24] = 2; break; }
      case ep12commstateCrunchingOrCrunched: { ep0.buf[24] = 3; break; }
      case ep12commstateWaitingForShipping:  { ep0.buf[24] = 4; break; }
      default:                               { ep0.buf[24] = 5; break; }
      }
    ep0.buf[25] = ep12.opc;
    ep0.buf[26] = ep0.useep0insteadofep1;
    ep0.buf[27] = ep0.manuallytriggeredep1shipping;
    ep0.buf[28] = mysfr8_IE;
    ep0.buf[29] = mysfr8_IP;
    ep0.buf[30] = mysfr8_EIE1;
    ep0.buf[31] = mysfr8_EIP1;
    ep0.buf[32] = mysfr8_EIE2;
    ep0.buf[33] = mysfr8_EIP2;
    ep0.buf[34] = lowGetUint8FromUsbReg (CUSB8_CMIE);
    ep0.buf[35] = lowGetUint8FromUsbReg (CUSB8_IN1IE);
    ep0.buf[36] = lowGetUint8FromUsbReg (CUSB8_OUT1IE);
    ep0.buf[37] = ep0.cmint;
    ep0.buf[38] = ep0.in1int;
    ep0.buf[39] = ep0.out1int;
    ep0.buf[40] = ep0.e0csr;
    ep0.buf[41] = ep0.eincsrl;
    ep0.buf[42] = ep0.eincsrh;
    ep0.buf[43] = ep0.eoutcsrl;
    ep0.buf[44] = ep0.eoutcsrh;
    ep0.buf[45] = ep0.cnt0ststl;
    ep0.buf[46] = ep0.cntin1int;
    ep0.buf[47] = (uint8_t) (dimcombuf        & (uint16_t) 0xff);
    ep0.buf[48] = (uint8_t) (dimcombuf   >> 8 & (uint16_t) 0xff);
    ep0.buf[49] = (uint8_t) (dimbytecode      & (uint16_t) 0xff);
    ep0.buf[50] = (uint8_t) (dimbytecode >> 8 & (uint16_t) 0xff);
    (void) usbReqEpi (0, &ep0.buf[0], 51, ep0.wLength, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetHai (void)
{
  if (ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength != 0) {
    ep0.wValue_lo = numberofusbstrings - 2;
    ep0.wValue = (uint16_t) ep0.wValue_lo;
    (void) usbReqEpi (lowGetUsbStrAsChrAdr (ep0.wValue_lo), 0,
                       lowGetUsbStrLen (ep0.wValue_lo), ep0.wLength, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqInpVenGetHrd (void)
{
  if (ep0.bmRequestType == 0xc0 /* 11000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength != 0) {
    ep0.wValue_lo = numberofusbstrings - 1;
    ep0.wValue = (uint16_t) ep0.wValue_lo;
    (void) usbReqEpi (lowGetUsbStrAsChrAdr (ep0.wValue_lo), 0,
                       lowGetUsbStrLen (ep0.wValue_lo), ep0.wLength, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVen (void)
{
  switch (ep0.bRequest) {
    case REQ_VEN_SET_DEBUGPACKAGE1:    { (void) reqOutVenSetDp1 (); return; }
    case REQ_VEN_SET_DEBUGPACKAGE2:    { (void) reqOutVenSetDp2 (); return; }
    case REQ_VEN_SET_GETCOUTPUTFROM0:  { (void) reqOutVenSetGf0 (); return; }
    case REQ_VEN_SET_GETCOUTPUTFROM1:  { (void) reqOutVenSetGf1 (); return; }
    case REQ_VEN_SET_SETEP12TOHALTED:  { (void) reqOutVenSetHlt (); return; }
    case REQ_VEN_SET_SETEP12TORUNNING: { (void) reqOutVenSetRun (); return; }
    case REQ_VEN_SET_SETEP1TRIGGERAUT: { (void) reqOutVenSetTia (); return; }
    case REQ_VEN_SET_SETEP1TRIGGERMAN: { (void) reqOutVenSetTim (); return; }
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetDp1 (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0x1111                     &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetDp2 (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0x2222                     &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetGf0 (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    ep0.useep0insteadofep1 = 1;
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetGf1 (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    ep0.useep0insteadofep1 = 0;
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetHlt (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    (void) lowSetEp12ToHaltedOrRunning (1, 1, 0);
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetRun (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    (void) lowSetEp12ToHaltedOrRunning (1, 1, 1);
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetTia (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    ep0.manuallytriggeredep1shipping = 0;
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
reqOutVenSetTim (void)
{
  if (ep0.bmRequestType == 0x40 /* 01000000 */ &&
      ep0.wValue == 0                          &&
      ep0.wIndex == 0                          &&
      ep0.wLength == 0) {
    ep0.manuallytriggeredep1shipping = 1;
    (void) usbReqEpi (0, 0, 0, 0, 0, 0);
    return;
    }
  (void) usbRequestReceptionErrorHandling ();
  return;
  }

/****************************************************************************/

static void
lowAbort (void)
{
  macMacMacAbort
  return;
  }

/****************************************************************************/

#if ((!defined (EXCLUDE_IFACES)) || (!defined (IMPLEMENT_A_CRUNCHER_STUB)))
static void
lowFlashMemoryWriteByte (volatile uint8_t mydatalocfast *pparam,
                          volatile uint8_t mydataloc *pflash)
{
  /* Enable writing to flash program memory.
     Ensure that the access to the parameters here
     does not cause the execution of a MOVX instruction. */
  mysfr8_PSCTL = *(pparam + 0);
  /* Write the key codes. */
  mysfr8_FLKEY = *(pparam + 1);
  mysfr8_FLKEY = *(pparam + 2);
  /* Now perform the write operation using the only MOVX instruction here.
     Due to the special preparation, `pflash' invisibly targets the flash
     memory and not the XRAM as it would normally be the case, but, of
     course, the compiler does not have any idea what is going on here. */
  *pflash = *(pparam + 3);
  /* Disable writing to flash program memory. */
  mysfr8_PSCTL = *(pparam + 4);
  return;
  }
#endif

/****************************************************************************/

static void
lowGetRandomBytesBase (volatile uint8_t mydataloc *mhzstate)
{
  macGetRandomBytesBase (mhzstate)
  return;
  }

/****************************************************************************/

static void
lowGetUint8ArrayFromFifo (uint8_t fifo, uint16_t cnt,
                           volatile uint8_t mydataloc *buf)
{
  macGetUint8ArrayFromFifo (fifo, cnt, buf)
  return;
  }

/****************************************************************************/

static uint8_t
lowGetUint8FromIndexedUsbReg (uint8_t indx, uint8_t usbreg)
{
  uint8_t mydataloc val;

  macGetUint8FromIndexedUsbReg (indx, usbreg, val)
  return (val);
  }

/****************************************************************************/

static uint8_t
lowGetUint8FromUsbReg (uint8_t usbreg)
{
  uint8_t mydataloc val;

  macGetUint8FromUsbReg (usbreg, val)
  return (val);
  }

/****************************************************************************/

static const usbtwostringdescriptor_t mycodeloc *
lowGetUsbStrAdr (uint8_t indx)
{
  static const usbtwostringdescriptor_t mycodeloc lastresort = {
    4, DESCR_TYPE_STRING, { '?', 0 }
    };

  switch (indx) {
    case 0:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &usbstringsupportedlangs ); }
    case 1:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &usbstringmanufacturer   ); }
    case 2:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &usbstringproduct        ); }
    case 3:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &usbstringserialnumber   ); }
    case 4:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &usbstringconfiguration  ); }
    case 5:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &usbstringinterface      ); }
    case 6:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &hiddenapplicationid     ); }
    case 7:  { return ( (const usbtwostringdescriptor_t mycodeloc *)
                        &hiddenreleasedate       ); }
    }
  return (&lastresort);
  }

/****************************************************************************/

static const uint8_t mycodeloc *
lowGetUsbStrAsChrAdr (uint8_t indx)
{
  return ((const uint8_t mycodeloc *) lowGetUsbStrAdr (indx));
  }

/****************************************************************************/

static uint16_t
lowGetUsbStrLen (uint8_t indx)
{
  return ((uint16_t) (lowGetUsbStrAdr (indx))->bLength);
  }

/****************************************************************************/

static void
lowMemCpyVol (volatile void mydataloc *t, const volatile void mydataloc *f,
               uint16_t n)
{
  uint16_t mydataloc i;

  for (i = 0; i < n; i++)
    *((volatile uint8_t mydataloc *) t + i) =
      *((const volatile uint8_t mydataloc *) f + i);
  return;
  }

/****************************************************************************/

static void
lowPutUint8ArrayToFifo (uint8_t fifo, uint16_t cnt,
                         const volatile uint8_t mydataloc *buf)
{
  macPutUint8ArrayToFifo (fifo, cnt, buf)
  return;
  }

/****************************************************************************/

static void
lowPutUint8CodeArrayToFifo (uint8_t fifo, uint16_t cnt,
                             const uint8_t mycodeloc *buf)
{
  macPutUint8CodeArrayToFifo (fifo, cnt, buf)
  return;
  }

/****************************************************************************/

static void
lowPutUint8ToIndexedUsbReg (uint8_t indx, uint8_t usbreg, uint8_t val)
{
  macPutUint8ToIndexedUsbReg (indx, usbreg, val)
  return;
  }

/****************************************************************************/

static void
lowPutUint8ToUsbReg (uint8_t usbreg, uint8_t val)
{
  macPutUint8ToUsbReg (usbreg, val)
  return;
  }

/****************************************************************************/

static void
lowPutZeroArrayToFifo (uint8_t fifo, uint16_t cnt)
{
  macPutZeroArrayToFifo (fifo, cnt)
  return;
  }

/****************************************************************************/

static void
lowRemoveUint8ArrayFromFifo (uint8_t fifo, uint16_t cnt)
{
  macRemoveUint8ArrayFromFifo (fifo, cnt)
  return;
  }

/****************************************************************************/

static void
lowSetEp12ToHaltedOrRunning (uint8_t ep1, uint8_t ep2, uint8_t running)
{
  macMacSetEp12ToHaltedOrRunning (ep1, ep2, running)
  return;
  }

/****************************************************************************/

static void
lowShipAnEp1Packet (uint8_t firstpacket)
{
  macMacShipAnEp1Packet (firstpacket)
  return;
  }

/****************************************************************************/


Stephan K.H. Seidl