text:
/***************************************************************************//**
 * @file
 * @brief Universal synchronous/asynchronous receiver/transmitter (USART/UART)
 *   peripheral API
 *******************************************************************************
 * # License
 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
 *******************************************************************************
 *
 * SPDX-License-Identifier: Zlib
 *
 * The licensor of this software is Silicon Laboratories Inc.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 ******************************************************************************/

#ifndef EM_USART_H
#define EM_USART_H

#include "em_device.h"
#if defined(USART_COUNT) && (USART_COUNT > 0)

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************//**
 * @addtogroup emlib
 * @{
 ******************************************************************************/

/***************************************************************************//**
 * @addtogroup USART
 * @brief Universal Synchronous/Asynchronous Receiver/Transmitter
 *   Peripheral API
 * @details
 * The Universal Synchronous/Asynchronous Receiver/Transmitter (USART)
 * is a very flexible serial I/O module. It supports full duplex asynchronous UART
 * communication as well as RS-485, SPI, MicroWire, and 3-wire. It can also interface
 * with ISO7816 Smart-Cards, and IrDA devices.
 *
 * The USART has a wide selection of operating modes, frame formats, and baud rates.
 * All features are supported through the API of this module.
 *
 * Triple buffering and DMA support makes high data-rates possible with minimal
 * CPU intervention. It is possible to transmit and receive large frames while
 * the MCU remains in EM1 Sleep.
 *
 * This module does not support DMA configuration. The @ref UARTDRV and @ref SPIDRV drivers
 * provide full support for DMA and more.
 *
 *  The following steps are necessary for basic operation:
 *
 *  Clock enable:
 *  @include em_usart_clock_enable.c
 *
 *  To initialize the USART for asynchronous operation (e.g., UART):
 *  @include em_usart_init_async.c
 *
 *  To initialize the USART for synchronous operation (e.g., SPI):
 *  @include em_usart_init_sync.c
 *
 *  After pins are assigned for the application/board, enable pins at the
 *  desired location. Available locations can be obtained from the Pin Definitions
 *  section in the data sheet.
 *  @if DOXYDOC_P1_DEVICE
 *  @include em_usart_route_p1.c
 *  @note UART hardware flow control is not directly supported in hardware on
 *        @ref _SILICON_LABS_32B_SERIES_0 parts.
 *  @endif
 *  @if DOXYDOC_P2_DEVICE
 *  @include em_usart_route_p2.c
 *  @endif
 *  @note @ref UARTDRV supports all types of UART flow control. Software assisted
 *        hardware flow control is available for parts without true UART hardware
 *        flow control.
 * @{
 ******************************************************************************/

/*******************************************************************************
 ********************************   ENUMS   ************************************
 ******************************************************************************/

/** Databit selection. */
typedef enum {
  usartDatabits4  = USART_FRAME_DATABITS_FOUR,     /**< 4 data bits (not available for UART). */
  usartDatabits5  = USART_FRAME_DATABITS_FIVE,     /**< 5 data bits (not available for UART). */
  usartDatabits6  = USART_FRAME_DATABITS_SIX,      /**< 6 data bits (not available for UART). */
  usartDatabits7  = USART_FRAME_DATABITS_SEVEN,    /**< 7 data bits (not available for UART). */
  usartDatabits8  = USART_FRAME_DATABITS_EIGHT,    /**< 8 data bits. */
  usartDatabits9  = USART_FRAME_DATABITS_NINE,     /**< 9 data bits. */
  usartDatabits10 = USART_FRAME_DATABITS_TEN,      /**< 10 data bits (not available for UART). */
  usartDatabits11 = USART_FRAME_DATABITS_ELEVEN,   /**< 11 data bits (not available for UART). */
  usartDatabits12 = USART_FRAME_DATABITS_TWELVE,   /**< 12 data bits (not available for UART). */
  usartDatabits13 = USART_FRAME_DATABITS_THIRTEEN, /**< 13 data bits (not available for UART). */
  usartDatabits14 = USART_FRAME_DATABITS_FOURTEEN, /**< 14 data bits (not available for UART). */
  usartDatabits15 = USART_FRAME_DATABITS_FIFTEEN,  /**< 15 data bits (not available for UART). */
  usartDatabits16 = USART_FRAME_DATABITS_SIXTEEN   /**< 16 data bits (not available for UART). */
} USART_Databits_TypeDef;

/** Enable selection. */
typedef enum {
  /** Disable both receiver and transmitter. */
  usartDisable  = 0x0,

  /** Enable receiver only, transmitter disabled. */
  usartEnableRx = USART_CMD_RXEN,

  /** Enable transmitter only, receiver disabled. */
  usartEnableTx = USART_CMD_TXEN,

  /** Enable both receiver and transmitter. */
  usartEnable   = (USART_CMD_RXEN | USART_CMD_TXEN)
} USART_Enable_TypeDef;

/** Oversampling selection, used for asynchronous operation. */
typedef enum {
  usartOVS16 = USART_CTRL_OVS_X16,     /**< 16x oversampling (normal). */
  usartOVS8  = USART_CTRL_OVS_X8,      /**< 8x oversampling. */
  usartOVS6  = USART_CTRL_OVS_X6,      /**< 6x oversampling. */
  usartOVS4  = USART_CTRL_OVS_X4       /**< 4x oversampling. */
} USART_OVS_TypeDef;

/** Parity selection, mainly used for asynchronous operation. */
typedef enum {
  usartNoParity   = USART_FRAME_PARITY_NONE,    /**< No parity. */
  usartEvenParity = USART_FRAME_PARITY_EVEN,    /**< Even parity. */
  usartOddParity  = USART_FRAME_PARITY_ODD      /**< Odd parity. */
} USART_Parity_TypeDef;

/** Stop bits selection, used for asynchronous operation. */
typedef enum {
  usartStopbits0p5 = USART_FRAME_STOPBITS_HALF,        /**< 0.5 stop bits. */
  usartStopbits1   = USART_FRAME_STOPBITS_ONE,         /**< 1 stop bits. */
  usartStopbits1p5 = USART_FRAME_STOPBITS_ONEANDAHALF, /**< 1.5 stop bits. */
  usartStopbits2   = USART_FRAME_STOPBITS_TWO          /**< 2 stop bits. */
} USART_Stopbits_TypeDef;

#if defined(_USART_ROUTEPEN_RTSPEN_MASK) && defined(_USART_ROUTEPEN_CTSPEN_MASK)
typedef enum {
  usartHwFlowControlNone = 0,
  usartHwFlowControlCts = USART_ROUTEPEN_CTSPEN,
  usartHwFlowControlRts = USART_ROUTEPEN_RTSPEN,
  usartHwFlowControlCtsAndRts = USART_ROUTEPEN_CTSPEN | USART_ROUTEPEN_RTSPEN,
} USART_HwFlowControl_TypeDef;

#elif defined(USART_CTRLX_CTSEN)
typedef enum {
  usartHwFlowControlNone = 0,
  usartHwFlowControlCts,
  usartHwFlowControlRts,
  usartHwFlowControlCtsAndRts
} USART_HwFlowControl_TypeDef;
#endif

/** Clock polarity/phase mode. */
typedef enum {
  /** Clock idle low, sample on rising edge. */
  usartClockMode0 = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLELEADING,

  /** Clock idle low, sample on falling edge. */
  usartClockMode1 = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLETRAILING,

  /** Clock idle high, sample on falling edge. */
  usartClockMode2 = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLELEADING,

  /** Clock idle high, sample on rising edge. */
  usartClockMode3 = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLETRAILING
} USART_ClockMode_TypeDef;

/** Pulse width selection for IrDA mode. */
typedef enum {
  /** IrDA pulse width is 1/16 for OVS=0 and 1/8 for OVS=1 */
  usartIrDAPwONE   = USART_IRCTRL_IRPW_ONE,

  /** IrDA pulse width is 2/16 for OVS=0 and 2/8 for OVS=1 */
  usartIrDAPwTWO   = USART_IRCTRL_IRPW_TWO,

  /** IrDA pulse width is 3/16 for OVS=0 and 3/8 for OVS=1 */
  usartIrDAPwTHREE = USART_IRCTRL_IRPW_THREE,

  /** IrDA pulse width is 4/16 for OVS=0 and 4/8 for OVS=1 */
  usartIrDAPwFOUR  = USART_IRCTRL_IRPW_FOUR
} USART_IrDAPw_Typedef;

/** PRS Channel type */
typedef uint8_t USART_PRS_Channel_t;

/** Deprecated PRS channel selector value.
 *  New code should use an integer instead. */
#define usartIrDAPrsCh0       0U
#define usartIrDAPrsCh1       1U
#define usartIrDAPrsCh2       2U
#define usartIrDAPrsCh3       3U
#define usartIrDAPrsCh4       4U
#define usartIrDAPrsCh5       5U
#define usartIrDAPrsCh6       6U
#define usartIrDAPrsCh7       7U
#define usartPrsRxCh0         0U
#define usartPrsRxCh1         1U
#define usartPrsRxCh2         2U
#define usartPrsRxCh3         3U
#define usartPrsRxCh4         4U
#define usartPrsRxCh5         5U
#define usartPrsRxCh6         6U
#define usartPrsRxCh7         7U
#define usartPrsRxCh8         8U
#define usartPrsRxCh9         9U
#define usartPrsRxCh10       10U
#define usartPrsRxCh11       11U
#define usartPrsTriggerCh0    0U
#define usartPrsTriggerCh1    1U
#define usartPrsTriggerCh2    2U
#define usartPrsTriggerCh3    3U
#define usartPrsTriggerCh4    4U
#define usartPrsTriggerCh5    5U
#define usartPrsTriggerCh6    6U
#define usartPrsTriggerCh7    7U

#if defined(_USART_I2SCTRL_MASK) && defined(USART_I2SCTRL_I2SEN)
/** I2S format selection. */
typedef enum {
  usartI2sFormatW32D32  = USART_I2SCTRL_I2SFORMAT_W32D32,   /**< 32-bit word, 32-bit data */
  usartI2sFormatW32D24M = USART_I2SCTRL_I2SFORMAT_W32D24M,  /**< 32-bit word, 32-bit data with 8 lsb masked */
  usartI2sFormatW32D24  = USART_I2SCTRL_I2SFORMAT_W32D24,   /**< 32-bit word, 24-bit data */
  usartI2sFormatW32D16  = USART_I2SCTRL_I2SFORMAT_W32D16,   /**< 32-bit word, 16-bit data */
  usartI2sFormatW32D8   = USART_I2SCTRL_I2SFORMAT_W32D8,    /**< 32-bit word, 8-bit data  */
  usartI2sFormatW16D16  = USART_I2SCTRL_I2SFORMAT_W16D16,   /**< 16-bit word, 16-bit data */
  usartI2sFormatW16D8   = USART_I2SCTRL_I2SFORMAT_W16D8,    /**< 16-bit word, 8-bit data  */
  usartI2sFormatW8D8    = USART_I2SCTRL_I2SFORMAT_W8D8      /**<  8-bit word, 8-bit data  */
} USART_I2sFormat_TypeDef;

/** I2S frame data justify. */
typedef enum {
  usartI2sJustifyLeft  = USART_I2SCTRL_I2SJUSTIFY_LEFT,  /**< Data is left-justified within the frame  */
  usartI2sJustifyRight = USART_I2SCTRL_I2SJUSTIFY_RIGHT  /**< Data is right-justified within the frame */
} USART_I2sJustify_TypeDef;

#elif defined(_USART_I2SCTRL_MASK)
/** I2S format selection. */
typedef enum {
  usartI2sFormatW32D32  = USART_I2SCTRL_FORMAT_W32D32,   /**< 32-bit word, 32-bit data. */
  usartI2sFormatW32D24M = USART_I2SCTRL_FORMAT_W32D24M,  /**< 32-bit word, 32-bit data with 8 lsb masked. */
  usartI2sFormatW32D24  = USART_I2SCTRL_FORMAT_W32D24,   /**< 32-bit word, 24-bit data. */
  usartI2sFormatW32D16  = USART_I2SCTRL_FORMAT_W32D16,   /**< 32-bit word, 16-bit data. */
  usartI2sFormatW32D8   = USART_I2SCTRL_FORMAT_W32D8,    /**< 32-bit word, 8-bit data.  */
  usartI2sFormatW16D16  = USART_I2SCTRL_FORMAT_W16D16,   /**< 16-bit word, 16-bit data. */
  usartI2sFormatW16D8   = USART_I2SCTRL_FORMAT_W16D8,    /**< 16-bit word, 8-bit data.  */
  usartI2sFormatW8D8    = USART_I2SCTRL_FORMAT_W8D8      /**<  8-bit word, 8-bit data.  */
} USART_I2sFormat_TypeDef;

/** I2S frame data justify. */
typedef enum {
  usartI2sJustifyLeft  = USART_I2SCTRL_JUSTIFY_LEFT,  /**< Data is left-justified within the frame.  */
  usartI2sJustifyRight = USART_I2SCTRL_JUSTIFY_RIGHT  /**< Data is right-justified within the frame. */
} USART_I2sJustify_TypeDef;
#endif

/*******************************************************************************
 *******************************   STRUCTS   ***********************************
 ******************************************************************************/

/** Asynchronous mode initialization structure. */
typedef struct {
  /** Specifies whether TX and/or RX is enabled when initialization is completed. */
  USART_Enable_TypeDef   enable;

  /**
   * USART/UART reference clock assumed when configuring baud rate setup.
   * Set to 0 to use the currently configured reference clock.
   */
  uint32_t               refFreq;

  /** Desired baud rate. */
  uint32_t               baudrate;

  /** Oversampling used. */
  USART_OVS_TypeDef      oversampling;

  /** Number of data bits in frame. Notice that UART modules only support 8 or
   * 9 data bits. */
  USART_Databits_TypeDef databits;

  /** Parity mode to use. */
  USART_Parity_TypeDef   parity;

  /** Number of stop bits to use. */
  USART_Stopbits_TypeDef stopbits;

#if !defined(_EFM32_GECKO_FAMILY)
  /** Majority Vote Disable for 16x, 8x and 6x oversampling modes. */
  bool                   mvdis;

  /** Enable USART Rx via PRS. */
  bool                   prsRxEnable;

  /** Select PRS channel for USART Rx. (Only valid if prsRxEnable is true). */
  USART_PRS_Channel_t    prsRxCh;
#endif

  /** Auto CS enabling. */
  bool                  autoCsEnable;

#if (_SILICON_LABS_32B_SERIES > 0)
  /** Auto CS hold time in baud cycles. */
  uint8_t               autoCsHold;

  /** Auto CS setup time in baud cycles. */
  uint8_t               autoCsSetup;

  /** Hardware flow control mode. */
  USART_HwFlowControl_TypeDef hwFlowControl;
#endif
} USART_InitAsync_TypeDef;

/** USART PRS trigger enable. */
typedef struct {
#if defined(USART_TRIGCTRL_AUTOTXTEN)
  /** Enable AUTOTX. */
  bool autoTxTriggerEnable;
#endif
  /** Trigger receive via PRS channel. */
  bool rxTriggerEnable;
  /** Trigger transmit via PRS channel. */
  bool txTriggerEnable;
  /** PRS channel to be used to trigger auto transmission. */
  USART_PRS_Channel_t prsTriggerChannel;
} USART_PrsTriggerInit_TypeDef;

/** Default configuration for USART asynchronous initialization structure. */
#if defined(_EFM32_GECKO_FAMILY)
/* Default USART Async struct for the EFM32G device */
#define USART_INITASYNC_DEFAULT                                                                    \
  {                                                                                \
    usartEnable,           /* Enable RX/TX when initialization is complete. */                     \
    0,                     /* Use current configured reference clock for configuring baud rate. */ \
    115200,                /* 115200 bits/s. */                                                    \
    usartOVS16,            /* 16x oversampling. */                                                 \
    usartDatabits8,        /* 8 data bits. */                                                      \
    usartNoParity,         /* No parity. */                                                        \
    usartStopbits1,        /* 1 stop bit. */                                                       \
    false,                 /* Auto CS functionality enable/disable switch */                       \
  }
#elif defined(_SILICON_LABS_32B_SERIES_0)
/* Default USART Async struct for Series 0 devices */
#define USART_INITASYNC_DEFAULT                                                                    \
  {                                                                                \
    usartEnable,           /* Enable RX/TX when initialization is complete. */                     \
    0,                     /* Use current configured reference clock for configuring baud rate. */ \
    115200,                /* 115200 bits/s. */                                                    \
    usartOVS16,            /* 16x oversampling. */                                                 \
    usartDatabits8,        /* 8 data bits. */                                                      \
    usartNoParity,         /* No parity. */                                                        \
    usartStopbits1,        /* 1 stop bit. */                                                       \
    false,                 /* Do not disable majority vote. */                                     \
    false,                 /* Not USART PRS input mode. */                                         \
    0,                     /* PRS channel 0. */                                                    \
    false,                 /* Auto CS functionality enable/disable switch */                       \
  }
#elif (_SILICON_LABS_32B_SERIES > 0)
/* Default USART Async struct for Series 1 and Series 2 devices */
#define USART_INITASYNC_DEFAULT                                                                    \
  {                                                                                \
    usartEnable,           /* Enable RX/TX when initialization is complete. */                     \
    0,                     /* Use current configured reference clock for configuring baud rate. */ \
    115200,                /* 115200 bits/s. */                                                    \
    usartOVS16,            /* 16x oversampling. */                                                 \
    usartDatabits8,        /* 8 data bits. */                                                      \
    usartNoParity,         /* No parity. */                                                        \
    usartStopbits1,        /* 1 stop bit. */                                                       \
    false,                 /* Do not disable majority vote. */                                     \
    false,                 /* Not USART PRS input mode. */                                         \
    0,                     /* PRS channel 0. */                                                    \
    false,                 /* Auto CS functionality enable/disable switch */                       \
    0,                     /* Auto CS Hold cycles */                                               \
    0,                     /* Auto CS Setup cycles */                                              \
    usartHwFlowControlNone /* No HW flow control */                                                \
  }
#endif

/** Default configuration for USART PRS triggering structure. */
#if defined(USART_TRIGCTRL_AUTOTXTEN)
#define USART_INITPRSTRIGGER_DEFAULT                            \
  {                                                             \
    false,             /* Do not enable autoTX triggering. */   \
    false,             /* Do not enable receive triggering. */  \
    false,             /* Do not enable transmit triggering. */ \
    0                  /* Set default channel to zero. */       \
  }
#else
#define USART_INITPRSTRIGGER_DEFAULT                            \
  {                                                             \
    false,             /* Do not enable receive triggering. */  \
    false,             /* Do not enable transmit triggering. */ \
    0                  /* Set default channel to zero. */       \
  }
#endif

/** Synchronous mode initialization structure. */
typedef struct {
  /** Specifies whether TX and/or RX shall be enabled when initialization is completed. */
  USART_Enable_TypeDef    enable;

  /**
   * USART/UART reference clock assumed when configuring baud rate setup.
   * Set to 0 to use the currently configured reference clock.
   */
  uint32_t                refFreq;

  /** Desired baud rate. */
  uint32_t                baudrate;

  /** Number of data bits in frame. */
  USART_Databits_TypeDef  databits;

  /** Select if to operate in master or slave mode. */
  bool                    master;

  /** Select if to send most or least significant bit first. */
  bool                    msbf;

  /** Clock polarity/phase mode. */
  USART_ClockMode_TypeDef clockMode;

#if !defined(_EFM32_GECKO_FAMILY)
  /** Enable USART Rx via PRS. */
  bool                    prsRxEnable;

  /** Select PRS channel for USART Rx. (Only valid if prsRxEnable is true). */
  USART_PRS_Channel_t     prsRxCh;
#endif

#if defined(USART_TRIGCTRL_AUTOTXTEN)
  /** Enable AUTOTX mode. Transmits as long as RX is not full.
   *  Generates underflows if TX is empty. */
  bool                    autoTx;
#endif

  /** Auto CS enabling */
  bool                    autoCsEnable;

#if defined(_USART_TIMING_CSHOLD_MASK)
  /** Auto CS hold time in baud cycles */
  uint8_t                 autoCsHold;

  /** Auto CS setup time in baud cycles */
  uint8_t                 autoCsSetup;
#endif
} USART_InitSync_TypeDef;

/** Default configuration for USART sync initialization structure. */
#if defined(_EFM32_GECKO_FAMILY)
/* Default USART Sync configuration for EFM32G devices. */
#define USART_INITSYNC_DEFAULT                                                               \
  {                                                                                \
    usartEnable,     /* Enable RX/TX when initialization is complete. */                     \
    0,               /* Use current configured reference clock for configuring baud rate. */ \
    1000000,         /* 1 Mbits/s. */                                                        \
    usartDatabits8,  /* 8 data bits. */                                                      \
    true,            /* Master mode. */                                                      \
    false,           /* Send least significant bit first. */                                 \
    usartClockMode0, /* Clock idle low, sample on rising edge. */                            \
    false,           /* No AUTOCS mode */                                                    \
  }
#elif defined(_SILICON_LABS_32B_SERIES_0)
/* Default USART Sync configuration for series 0 devices. */
#define USART_INITSYNC_DEFAULT                                                               \
  {                                                                                \
    usartEnable,     /* Enable RX/TX when initialization is complete. */                     \
    0,               /* Use current configured reference clock for configuring baud rate. */ \
    1000000,         /* 1 Mbits/s. */                                                        \
    usartDatabits8,  /* 8 data bits. */                                                      \
    true,            /* Master mode. */                                                      \
    false,           /* Send least significant bit first. */                                 \
    usartClockMode0, /* Clock idle low, sample on rising edge. */                            \
    false,           /* Not USART PRS input mode. */                                         \
    0,               /* PRS channel 0. */                                                    \
    false,           /* No AUTOTX mode. */                                                   \
    false,           /* No AUTOCS mode */                                                    \
  }
#elif (_SILICON_LABS_32B_SERIES > 0)
/* Default USART Sync configuration for series 2 devices */
#define USART_INITSYNC_DEFAULT                                                               \
  {                                                                                \
    usartEnable,     /* Enable RX/TX when initialization is complete. */                     \
    0,               /* Use current configured reference clock for configuring baud rate. */ \
    1000000,         /* 1 Mbits/s. */                                                        \
    usartDatabits8,  /* 8 databits. */                                                       \
    true,            /* Master mode. */                                                      \
    false,           /* Send least significant bit first. */                                 \
    usartClockMode0, /* Clock idle low, sample on rising edge. */                            \
    false,           /* Not USART PRS input mode. */                                         \
    0,               /* PRS channel 0. */                                                    \
    false,           /* No AUTOTX mode. */                                                   \
    false,           /* No AUTOCS mode. */                                                   \
    0,               /* Auto CS Hold cycles. */                                              \
    0                /* Auto CS Setup cycles. */                                             \
  }
#endif

/** IrDA mode initialization structure. Inherited from asynchronous mode initialization structure. */
typedef struct {
  /** General Asynchronous initialization structure. */
  USART_InitAsync_TypeDef  async;

  /** Set to invert Rx signal before IrDA demodulator. */
  bool                     irRxInv;

  /** Set to enable filter on IrDA demodulator. */
  bool                     irFilt;

  /** Configure the pulse width generated by the IrDA modulator as a fraction
   *  of the configured USART bit period. */
  USART_IrDAPw_Typedef     irPw;

  /** Enable the PRS channel selected by irPrsSel as input to IrDA module
   *  instead of TX. */
  bool                     irPrsEn;

  /** PRS can be used as input to the pulse modulator instead of TX.
   *  This value selects the channel to use. */
  USART_PRS_Channel_t      irPrsSel;
} USART_InitIrDA_TypeDef;

/** Default configuration for IrDA mode initialization structure. */
#if defined(_EFM32_GECKO_FAMILY)
/* Default USART IrDA struct for the EFM32G device */
#define USART_INITIRDA_DEFAULT                                                                       \
  {                                                                                \
    {                                                                                \
      usartEnable,           /* Enable RX/TX when initialization is complete. */                     \
      0,                     /* Use current configured reference clock for configuring baud rate. */ \
      115200,                /* 115200 bits/s. */                                                    \
      usartOVS16,            /* 16x oversampling. */                                                 \
      usartDatabits8,        /* 8 data bits. */                                                      \
      usartEvenParity,       /* Even parity. */                                                      \
      usartStopbits1,        /* 1 stop bit. */                                                       \
      false,                 /* Auto CS functionality enable/disable switch */                       \
    },                                                                                \
    false,            /* Rx invert disabled. */                                                      \
    false,            /* Filtering disabled. */                                                      \
    usartIrDAPwTHREE, /* Pulse width is set to ONE. */                                               \
    false,            /* Routing to PRS is disabled. */                                              \
    0                 /* PRS channel 0. */                                                           \
  }
#elif defined(_SILICON_LABS_32B_SERIES_0)
/* Default USART IrDA struct for Series 0 devices */
#define USART_INITIRDA_DEFAULT                                                                       \
  {                                                                                \
    {                                                                                \
      usartEnable,           /* Enable RX/TX when initialization is complete. */                     \
      0,                     /* Use current configured reference clock for configuring baud rate. */ \
      115200,                /* 115200 bits/s. */                                                    \
      usartOVS16,            /* 16x oversampling. */                                                 \
      usartDatabits8,        /* 8 data bits. */                                                      \
      usartEvenParity,       /* Even parity. */                                                      \
      usartStopbits1,        /* 1 stop bit. */                                                       \
      false,                 /* Do not disable majority vote. */                                     \
      false,                 /* Not USART PRS input mode. */                                         \
      0,                     /* PRS channel 0. */                                                    \
      false,                 /* Auto CS functionality enable/disable switch */                       \
    },                                                                                \
    false,            /* Rx invert disabled. */                                                      \
    false,            /* Filtering disabled. */                                                      \
    usartIrDAPwTHREE, /* Pulse width is set to ONE. */                                               \
    false,            /* Routing to PRS is disabled. */                                              \
    0                 /* PRS channel 0. */                                                           \
  }
#elif (_SILICON_LABS_32B_SERIES > 0)
/* Default USART IrDA struct for Series 1 and Series 2 devices */
#define USART_INITIRDA_DEFAULT                                                                       \
  {                                                                                \
    {                                                                                \
      usartEnable,           /* Enable RX/TX when initialization is complete. */                     \
      0,                     /* Use current configured reference clock for configuring baud rate. */ \
      115200,                /* 115200 bits/s. */                                                    \
      usartOVS16,            /* 16x oversampling. */                                                 \
      usartDatabits8,        /* 8 data bits. */                                                      \
      usartEvenParity,       /* Even parity. */                                                      \
      usartStopbits1,        /* 1 stop bit. */                                                       \
      false,                 /* Do not disable majority vote. */                                     \
      false,                 /* Not USART PRS input mode. */                                         \
      0,                     /* PRS channel 0. */                                                    \
      false,                 /* Auto CS functionality enable/disable switch */                       \
      0,                     /* Auto CS Hold cycles */                                               \
      0,                     /* Auto CS Setup cycles */                                              \
      usartHwFlowControlNone /* No HW flow control */                                                \
    },                                                                                \
    false,            /* Rx invert disabled. */                                                      \
    false,            /* Filtering disabled. */                                                      \
    usartIrDAPwTHREE, /* Pulse width is set to ONE. */                                               \
    false,            /* Routing to PRS is disabled. */                                              \
    0                 /* PRS channel 0. */                                                           \
  }
#endif

#if defined(_USART_I2SCTRL_MASK)
/** I2S mode initialization structure. Inherited from synchronous mode initialization structure. */
typedef struct {
  /** General Synchronous initialization structure. */
  USART_InitSync_TypeDef   sync;

  /** I2S mode. */
  USART_I2sFormat_TypeDef  format;

  /** Delay on I2S data. Set to add a one-cycle delay between a transition
   *  on the word-clock and the start of the I2S word.
   *  Should be set for standard I2S format. */
  bool                     delay;

  /** Separate DMA Request For Left/Right Data. */
  bool                     dmaSplit;

  /** Justification of I2S data within the frame. */
  USART_I2sJustify_TypeDef justify;

  /** Stereo or Mono, set to true for mono. */
  bool                     mono;
} USART_InitI2s_TypeDef;

/** Default configuration for I2S mode initialization structure. */
#if defined(_EFM32_GECKO_FAMILY)
/* Default USART Sync configuration for EFM32G devices. */
#define USART_INITI2S_DEFAULT                                                                  \
  {                                                                                \
    {                                                                                \
      usartEnable,     /* Enable RX/TX when initialization is complete. */                     \
      0,               /* Use current configured reference clock for configuring baud rate. */ \
      1000000,         /* 1 Mbits/s. */                                                        \
      usartDatabits16, /* 16 databits. */                                                      \
      true,            /* Master mode. */                                                      \
      true,            /* Most significant bit first. */                                       \
      usartClockMode0, /* Clock idle low, sample on rising edge. */                            \
      false,           /* No AUTOCS mode */                                                    \
    },                                                                                \
    usartI2sFormatW16D16, /* 16-bit word, 16-bit data */                                       \
    true,               /* Delay on I2S data. */                                               \
    false,              /* No DMA split. */                                                    \
    usartI2sJustifyLeft,/* Data is left-justified within the frame */                          \
    false               /* Stereo mode. */                                                     \
  }
#elif defined(_SILICON_LABS_32B_SERIES_0)
/* Default USART Sync configuration for series 0 devices. */
#define USART_INITI2S_DEFAULT                                                                  \
  {                                                                                \
    {                                                                                \
      usartEnable,     /* Enable RX/TX when initialization is complete. */                     \
      0,               /* Use current configured reference clock for configuring baud rate. */ \
      1000000,         /* 1 Mbits/s. */                                                        \
      usartDatabits16, /* 16 databits. */                                                      \
      true,            /* Master mode. */                                                      \
      true,            /* Most significant bit first. */                                       \
      usartClockMode0, /* Clock idle low, sample on rising edge. */                            \
      false,           /* Not USART PRS input mode. */                                         \
      0,               /* PRS channel 0. */                                                    \
      false,           /* No AUTOTX mode. */                                                   \
      false,           /* No AUTOCS mode */                                                    \
    },                                                                                \
    usartI2sFormatW16D16, /* 16-bit word, 16-bit data */                                       \
    true,               /* Delay on I2S data. */                                               \
    false,              /* No DMA split. */                                                    \
    usartI2sJustifyLeft,/* Data is left-justified within the frame */                          \
    false               /* Stereo mode. */                                                     \
  }
#elif (_SILICON_LABS_32B_SERIES > 0)
/* Default USART Sync configuration for series 2 devices */
#define USART_INITI2S_DEFAULT                                                                  \
  {                                                                                \
    {                                                                                \
      usartEnableTx,    /* Enable TX when init completed. */                                   \
      0,                /* Use current configured reference clock for configuring baudrate. */ \
      1000000,          /* Baudrate 1M bits/s. */                                              \
      usartDatabits16,  /* 16 databits. */                                                     \
      true,             /* Operate as I2S master. */                                           \
      true,             /* Most significant bit first. */                                      \
      usartClockMode0,  /* Clock idle low, sample on rising edge. */                           \
      false,            /* Don't enable USARTRx via PRS. */                                    \
      usartPrsRxCh0,    /* PRS channel selection (dummy). */                                   \
      false,            /* Disable AUTOTX mode. */                                             \
      false,            /* No AUTOCS mode */                                                   \
      0,                /* Auto CS Hold cycles */                                              \
      0                 /* Auto CS Setup cycles */                                             \
    },                                                                                \
    usartI2sFormatW16D16, /* 16-bit word, 16-bit data */                                       \
    true,               /* Delay on I2S data. */                                               \
    false,              /* No DMA split. */                                                    \
    usartI2sJustifyLeft,/* Data is left-justified within the frame */                          \
    false               /* Stereo mode. */                                                     \
  }
#endif
#endif

/*******************************************************************************
 *****************************   PROTOTYPES   **********************************
 ******************************************************************************/

void USART_BaudrateAsyncSet(USART_TypeDef *usart,
                            uint32_t refFreq,
                            uint32_t baudrate,
                            USART_OVS_TypeDef ovs);
uint32_t USART_BaudrateCalc(uint32_t refFreq,
                            uint32_t clkdiv,
                            bool syncmode,
                            USART_OVS_TypeDef ovs);
uint32_t USART_BaudrateGet(USART_TypeDef *usart);
void USART_BaudrateSyncSet(USART_TypeDef *usart,
                           uint32_t refFreq,
                           uint32_t baudrate);
void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable);

void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init);
void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init);
void USARTn_InitIrDA(USART_TypeDef *usart, const USART_InitIrDA_TypeDef *init);

#if defined(_USART_I2SCTRL_MASK)
void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init);
#endif
void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init);

#if defined(DEFAULT_IRDA_USART) || defined(USART0) || ((USART_COUNT == 1) && defined(USART1))
/***************************************************************************//**
 * @brief
 *   Initialization DEFAULT_IRDA_USART for asynchronous IrDA mode.
 *
 * @details
 *   This function will configure basic settings in order to operate in
 *   asynchronous IrDA mode.
 *
 *   Special control setup not covered by this function must be done after
 *   using this function by direct modification of the CTRL and IRCTRL
 *   registers.
 *
 *   Notice that pins used by the USART/UART module must be properly configured
 *   by the user explicitly for the USART/UART to work as intended.
 *   (When configuring pins, one should remember to consider the sequence of
 *   configuration to avoid unintended pulses/glitches on output
 *   pins.)
 *
 * @param[in] init
 *   Pointer to initialization structure used to configure asynchronous IrDA setup.
 *
 * @deprecated
 *   Deprecated function. New code should use USARTn_InitIrDA().
 *   This function uses DEFAULT_IRDA_USART, which unless otherwise specified, is
 *   USART0 on most devices, and USART1 on devices that don't have a USART0.
 *
 ******************************************************************************/
__STATIC_INLINE void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
{
#if defined(DEFAULT_IRDA_USART)
  USART_TypeDef *usart = DEFAULT_IRDA_USART;
#elif (USART_COUNT == 1) && defined(USART1)
  USART_TypeDef *usart = USART1;
#else
  USART_TypeDef *usart = USART0;
#endif
  USARTn_InitIrDA(usart, init);
}
#endif

/***************************************************************************//**
 * @brief
 *   Clear one or more pending USART interrupts.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @param[in] flags
 *   Pending USART/UART interrupt source(s) to clear. Use one or more valid
 *   interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
 ******************************************************************************/
__STATIC_INLINE void USART_IntClear(USART_TypeDef *usart, uint32_t flags)
{
#if defined (USART_HAS_SET_CLEAR)
  usart->IF_CLR = flags;
#else
  usart->IFC = flags;
#endif
}

/***************************************************************************//**
 * @brief
 *   Disable one or more USART interrupts.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @param[in] flags
 *   USART/UART interrupt source(s) to disable. Use one or more valid
 *   interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
 ******************************************************************************/
__STATIC_INLINE void USART_IntDisable(USART_TypeDef *usart, uint32_t flags)
{
  usart->IEN &= ~flags;
}

/***************************************************************************//**
 * @brief
 *   Enable one or more USART interrupts.
 *
 * @note
 *   Depending on the use, a pending interrupt may already be set prior to
 *   enabling the interrupt. To ignore a pending interrupt, consider using
 *   USART_IntClear() prior to enabling the interrupt.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @param[in] flags
 *   USART/UART interrupt source(s) to enable. Use one or more valid
 *   interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
 ******************************************************************************/
__STATIC_INLINE void USART_IntEnable(USART_TypeDef *usart, uint32_t flags)
{
  usart->IEN |= flags;
}

/***************************************************************************//**
 * @brief
 *   Get pending USART interrupt flags.
 *
 * @note
 *   The event bits are not cleared by the use of this function.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @return
 *   USART/UART interrupt source(s) pending. Returns one or more valid
 *   interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
 ******************************************************************************/
__STATIC_INLINE uint32_t USART_IntGet(USART_TypeDef *usart)
{
  return usart->IF;
}

/***************************************************************************//**
 * @brief
 *   Get enabled and pending USART interrupt flags.
 *   Useful for handling more interrupt sources in the same interrupt handler.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @note
 *   Interrupt flags are not cleared by the use of this function.
 *
 * @return
 *   Pending and enabled USART interrupt sources.
 *   The return value is the bitwise AND combination of
 *   - the OR combination of enabled interrupt sources in USARTx_IEN_nnn
 *     register (USARTx_IEN_nnn) and
 *   - the OR combination of valid interrupt flags of the USART module
 *     (USARTx_IF_nnn).
 ******************************************************************************/
__STATIC_INLINE uint32_t USART_IntGetEnabled(USART_TypeDef *usart)
{
  uint32_t ien;

  /* Store USARTx->IEN in temporary variable in order to define explicit order
   * of volatile accesses. */
  ien = usart->IEN;

  /* Bitwise AND of pending and enabled interrupts. */
  return usart->IF & ien;
}

/***************************************************************************//**
 * @brief
 *   Set one or more pending USART interrupts from SW.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @param[in] flags
 *   USART/UART interrupt source(s) to set to pending. Use one or more valid
 *   interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
 ******************************************************************************/
__STATIC_INLINE void USART_IntSet(USART_TypeDef *usart, uint32_t flags)
{
#if defined (USART_HAS_SET_CLEAR)
  usart->IF_SET = flags;
#else
  usart->IFS = flags;
#endif
}

/***************************************************************************//**
 * @brief
 *   Get USART STATUS register.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @return
 *  STATUS register value.
 *
 ******************************************************************************/
__STATIC_INLINE uint32_t USART_StatusGet(USART_TypeDef *usart)
{
  return usart->STATUS;
}

void USART_Reset(USART_TypeDef *usart);
uint8_t USART_Rx(USART_TypeDef *usart);
uint16_t USART_RxDouble(USART_TypeDef *usart);
uint32_t USART_RxDoubleExt(USART_TypeDef *usart);
uint16_t USART_RxExt(USART_TypeDef *usart);

/***************************************************************************//**
 * @brief
 *   Receive one 4-8 bit frame, (or part of 10-16 bit frame).
 *
 * @details
 *   This function is used to quickly receive one 4-8 bits frame by reading the
 *   RXDATA register directly, without checking the STATUS register for the
 *   RXDATAV flag. This can be useful from the RXDATAV interrupt handler,
 *   i.e., waiting is superfluous, in order to quickly read the received data.
 *   Please refer to @ref USART_RxDataXGet() for reception of 9 bit frames.
 *
 * @note
 *   Since this function does not check whether the RXDATA register actually
 *   holds valid data, it should only be used in situations when it is certain
 *   that there is valid data, ensured by some external program routine, e.g.,
 *   when handling an RXDATAV interrupt. The @ref USART_Rx() is normally a
 *   better choice if the validity of the RXDATA register is not certain.
 *
 * @note
 *   Notice that possible parity/stop bits in asynchronous mode are not
 *   considered part of specified frame bit length.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @return
 *   Data received.
 ******************************************************************************/
__STATIC_INLINE uint8_t USART_RxDataGet(USART_TypeDef *usart)
{
  return (uint8_t)usart->RXDATA;
}

/***************************************************************************//**
 * @brief
 *   Receive two 4-8 bit frames, or one 10-16 bit frame.
 *
 * @details
 *   This function is used to quickly receive one 10-16 bits frame or two 4-8
 *   bit frames by reading the RXDOUBLE register directly, without checking
 *   the STATUS register for the RXDATAV flag. This can be useful from the
 *   RXDATAV interrupt handler, i.e., waiting is superfluous, in order to
 *   quickly read the received data.
 *   This function is normally used to receive one frame when operating with
 *   frame length 10-16 bits. Please refer to @ref USART_RxDoubleXGet()
 *   for reception of two 9 bit frames.
 *
 * @note
 *   Since this function does not check whether the RXDOUBLE register actually
 *   holds valid data, it should only be used in situations when it is certain
 *   that there is valid data, ensured by some external program routine, e.g.,
 *   when handling an RXDATAV interrupt. The @ref USART_RxDouble() is
 *   normally a better choice if the validity of the RXDOUBLE register is not
 *   certain.
 *
 * @note
 *   Notice that possible parity/stop bits in asynchronous mode are not
 *   considered part of specified frame bit length.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @return
 *   Data received.
 ******************************************************************************/
__STATIC_INLINE uint16_t USART_RxDoubleGet(USART_TypeDef *usart)
{
  return (uint16_t)usart->RXDOUBLE;
}

/***************************************************************************//**
 * @brief
 *   Receive two 4-9 bit frames, or one 10-16 bit frame with extended
 *   information.
 *
 * @details
 *   This function is used to quickly receive one 10-16 bits frame or two 4-9
 *   bit frames by reading the RXDOUBLEX register directly, without checking
 *   the STATUS register for the RXDATAV flag. This can be useful from the
 *   RXDATAV interrupt handler, i.e., waiting is superfluous, in order to
 *   quickly read the received data.
 *
 * @note
 *   Since this function does not check whether the RXDOUBLEX register actually
 *   holds valid data, it should only be used in situations when it is certain
 *   that there is valid data, ensured by some external program routine, e.g.,
 *   when handling an RXDATAV interrupt. The @ref USART_RxDoubleExt() is
 *   normally a better choice if the validity of the RXDOUBLEX register is not
 *   certain.
 *
 * @note
 *   Notice that possible parity/stop bits in asynchronous mode are not
 *   considered part of specified frame bit length.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @return
 *   Data received.
 ******************************************************************************/
__STATIC_INLINE uint32_t USART_RxDoubleXGet(USART_TypeDef *usart)
{
  return usart->RXDOUBLEX;
}

/***************************************************************************//**
 * @brief
 *   Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
 *   information.
 *
 * @details
 *   This function is used to quickly receive one 4-9 bit frame, (or part of
 *   10-16 bit frame) with extended information by reading the RXDATAX register
 *   directly, without checking the STATUS register for the RXDATAV flag. This
 *   can be useful from the RXDATAV interrupt handler, i.e., waiting is
 *   superfluous, in order to quickly read the received data.
 *
 * @note
 *   Since this function does not check whether the RXDATAX register actually
 *   holds valid data, it should only be used in situations when it is certain
 *   that there is valid data, ensured by some external program routine, e.g.,
 *   when handling an RXDATAV interrupt. The @ref USART_RxExt() is normally
 *   a better choice if the validity of the RXDATAX register is not certain.
 *
 * @note
 *   Notice that possible parity/stop bits in asynchronous mode are not
 *   considered part of specified frame bit length.
 *
 * @param[in] usart
 *   Pointer to USART/UART peripheral register block.
 *
 * @return
 *   Data received.
 ******************************************************************************/
__STATIC_INLINE uint16_t USART_RxDataXGet(USART_TypeDef *usart)
{
  return (uint16_t)usart->RXDATAX;
}

uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data);
void USART_Tx(USART_TypeDef *usart, uint8_t data);
void USART_TxDouble(USART_TypeDef *usart, uint16_t data);
void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data);
void USART_TxExt(USART_TypeDef *usart, uint16_t data);

/** @} (end addtogroup USART) */
/** @} (end addtogroup emlib) */

#ifdef __cplusplus
}
#endif

#endif /* defined(USART_COUNT) && (USART_COUNT > 0) */
#endif /* EM_USART_H */


text:
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;

namespace JiiLib.Media.Metadata.Mp3
{
    public sealed class Mp3File : MediaFile
    {
        public Mp3File(FileInfo fileInfo) : base(fileInfo) { }
        public Mp3File(string path) : base(path) { }

        internal static bool Create(FileInfo file, [NotNullWhen(true)] out MediaFile mediaFile)
        {
            mediaFile = new Mp3File(file);
            return true;
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
#ifndef _WIN32
#include <unistd.h>
#endif

#include <pkcs11/p11generic.h>
#include <pkcs11/session.h>
#include <pkcs11/slot.h>
#include <pkcs11/slotpool.h>
#include <pkcs11/token.h>
#include <pkcs11/crypto.h>
#include <common/debug.h>

extern struct p11Context_t *context;

/*  C_EncryptInit initializes an encryption operation. */
CK_DECLARE_FUNCTION(CK_RV, C_EncryptInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hKey
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, hKey, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_EncryptInit != NULL) {
		rv = pObject->C_EncryptInit(pObject, pMechanism);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported");
	}

	if (rv == CKR_OK) {
		pSession->activeObjectHandle = pObject->handle;
		rv = copyMechanismParameter(pSession, pMechanism);
	}

	FUNC_RETURNS(rv);
}

/*  C_Encrypt encrypts single-part data. */
CK_DECLARE_FUNCTION(CK_RV, C_Encrypt)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pData,
		CK_ULONG ulDataLen,
		CK_BYTE_PTR pEncryptedData,
		CK_ULONG_PTR pulEncryptedDataLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (pEncryptedData && !isValidPtr(pEncryptedData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulEncryptedDataLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_Encrypt != NULL) {
		rv = pObject->C_Encrypt(pObject, &pSession->activeMechanism, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen);

		if ((pEncryptedData != NULL) && (rv != CKR_BUFFER_TOO_SMALL)) {
			pSession->activeObjectHandle = CK_INVALID_HANDLE;
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported");
	}

	FUNC_RETURNS(rv);
}

/*  C_EncryptUpdate continues a multiple-part encryption operation,
    processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_EncryptUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pPart,
		CK_ULONG ulPartLen,
		CK_BYTE_PTR pEncryptedPart,
		CK_ULONG_PTR pulEncryptedPartLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (pEncryptedPart && !isValidPtr(pEncryptedPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulEncryptedPartLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_EncryptUpdate != NULL) {
		rv = pObject->C_EncryptUpdate(pObject, &pSession->activeMechanism, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	FUNC_RETURNS(rv);
}

/*  C_EncryptFinal finishes a multiple-part encryption operation. */
CK_DECLARE_FUNCTION(CK_RV, C_EncryptFinal)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pLastEncryptedPart,
		CK_ULONG_PTR pulLastEncryptedPartLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (pLastEncryptedPart && !isValidPtr(pLastEncryptedPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulLastEncryptedPartLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_EncryptFinal != NULL) {
		rv = pObject->C_EncryptFinal(pObject, &pSession->activeMechanism, pLastEncryptedPart, pulLastEncryptedPartLen);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	if (!rv) {
		pSession->activeObjectHandle = CK_INVALID_HANDLE;
		rv = CKR_OK;
	}

	FUNC_RETURNS(rv);
}

/*  C_DecryptInit initializes a decryption operation. */
CK_DECLARE_FUNCTION(CK_RV, C_DecryptInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hKey
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, hKey, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_DecryptInit != NULL) {
		rv = pObject->C_DecryptInit(pObject, pMechanism);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	if (!rv) {
		pSession->activeObjectHandle = pObject->handle;
		rv = copyMechanismParameter(pSession, pMechanism);
	}

	FUNC_RETURNS(rv);
}

/*  C_Decrypt decrypts encrypted data in a single part. */
CK_DECLARE_FUNCTION(CK_RV, C_Decrypt)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pEncryptedData,
		CK_ULONG ulEncryptedDataLen,
		CK_BYTE_PTR pData,
		CK_ULONG_PTR pulDataLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pEncryptedData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (pData && !isValidPtr(pData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulDataLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pData != NULL) {
		pSession->activeObjectHandle = CK_INVALID_HANDLE;
	}

	if (pObject->C_Decrypt != NULL) {
		rv = pObject->C_Decrypt(pObject, &pSession->activeMechanism, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	FUNC_RETURNS(rv);
}

/*  C_DecryptUpdate continues a multiple-part decryption operation,
    processing another encrypted data part. */
CK_DECLARE_FUNCTION(CK_RV, C_DecryptUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pEncryptedPart,
		CK_ULONG ulEncryptedPartLen,
		CK_BYTE_PTR pPart,
		CK_ULONG_PTR pulPartLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pEncryptedPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (pPart && !isValidPtr(pPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulPartLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_DecryptUpdate != NULL) {
		rv = pObject->C_DecryptUpdate(pObject, &pSession->activeMechanism, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	FUNC_RETURNS(rv);
}

/*  C_DecryptFinal finishes a multiple-part decryption operation. */
CK_DECLARE_FUNCTION(CK_RV, C_DecryptFinal)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pLastPart,
		CK_ULONG_PTR pulLastPartLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (pLastPart && !isValidPtr(pLastPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulLastPartLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}
	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_DecryptFinal != NULL) {
		rv = pObject->C_DecryptFinal(pObject, &pSession->activeMechanism, pLastPart, pulLastPartLen);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	if (!rv) {
		pSession->activeObjectHandle = CK_INVALID_HANDLE;
		rv = CKR_OK;
	}

	FUNC_RETURNS(rv);
}

/*  C_DigestInit initializes a message-digesting operation. */
CK_DECLARE_FUNCTION(CK_RV, C_DigestInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism
)
{
	struct p11Session_t *pSession;
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

#ifdef ENABLE_LIBCRYPTO
	rv = cryptoDigestInit(pSession, pMechanism);
#endif

	FUNC_RETURNS(rv);
}

/*  C_Digest digests data in a single part. */
CK_DECLARE_FUNCTION(CK_RV, C_Digest)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pData,
		CK_ULONG ulDataLen,
		CK_BYTE_PTR pDigest,
		CK_ULONG_PTR pulDigestLen
)
{
	struct p11Session_t *pSession;
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (pData && !isValidPtr(pData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulDigestLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

#ifdef ENABLE_LIBCRYPTO
	rv = cryptoDigest(pSession, pData, ulDataLen, pDigest, pulDigestLen);
#endif

	FUNC_RETURNS(rv);
}

/*  C_DigestUpdate continues a multiple-part message-digesting operation,
    processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_DigestUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pPart,
		CK_ULONG ulPartLen
)
{
	struct p11Session_t *pSession;
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

#ifdef ENABLE_LIBCRYPTO
	rv = cryptoDigestUpdate(pSession, pPart, ulPartLen);
#endif

	FUNC_RETURNS(rv);
}

/*  C_DigestKey continues a multiple-part message-digesting operation by
    digesting the value of a secret key. */
CK_DECLARE_FUNCTION(CK_RV, C_DigestKey)(
		CK_SESSION_HANDLE hSession,
		CK_OBJECT_HANDLE hKey
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_DigestFinal finishes a multiple-part message-digesting operation. */
CK_DECLARE_FUNCTION(CK_RV, C_DigestFinal)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pDigest,
		CK_ULONG_PTR pulDigestLen
)
{
	struct p11Session_t *pSession;
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (pDigest && !isValidPtr(pDigest)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulDigestLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

#ifdef ENABLE_LIBCRYPTO
	rv = cryptoDigestFinal(pSession, pDigest, pulDigestLen);
#endif

	FUNC_RETURNS(rv);
}

/*  C_SignInit initializes a signature operation,
    here the signature is an appendix to the data. */
CK_DECLARE_FUNCTION(CK_RV, C_SignInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hKey
)
{
	int rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, hKey, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_SignInit != NULL) {
		rv = pObject->C_SignInit(pObject, pMechanism);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	if (!rv) {
		pSession->activeObjectHandle = pObject->handle;
		rv = copyMechanismParameter(pSession, pMechanism);
	}

	FUNC_RETURNS(rv);
}

/*  C_Sign signs data in a single part, where the signature is an appendix to the data. */
CK_DECLARE_FUNCTION(CK_RV, C_Sign)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pData,
		CK_ULONG ulDataLen,
		CK_BYTE_PTR pSignature,
		CK_ULONG_PTR pulSignatureLen
)
{
	int rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (pSignature && !isValidPtr(pSignature)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulSignatureLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_Sign != NULL) {
		rv = pObject->C_Sign(pObject, &pSession->activeMechanism, pData, ulDataLen, pSignature, pulSignatureLen);

		if ((pSignature != NULL) && (rv != CKR_BUFFER_TOO_SMALL)) {
			pSession->activeObjectHandle = CK_INVALID_HANDLE;
		}

		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	FUNC_RETURNS(rv);
}

/*  C_SignUpdate continues a multiple-part signature operation,
    processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_SignUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pPart,
		CK_ULONG ulPartLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_SignUpdate != NULL) {
		rv = pObject->C_SignUpdate(pObject, &pSession->activeMechanism, pPart, ulPartLen);
		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		rv = appendToCryptoBuffer(pSession, pPart, ulPartLen);
	}

	FUNC_RETURNS(rv);
}

/*  C_SignFinal finishes a multiple-part signature operation. */
CK_DECLARE_FUNCTION(CK_RV, C_SignFinal)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pSignature,
		CK_ULONG_PTR pulSignatureLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (pSignature && !isValidPtr(pSignature)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pulSignatureLen)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, pSession->activeObjectHandle, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_SignFinal != NULL) {
		rv = pObject->C_SignFinal(pObject, &pSession->activeMechanism, pSignature, pulSignatureLen);

		if ((pSignature != NULL) && (rv != CKR_BUFFER_TOO_SMALL)) {
			pSession->activeObjectHandle = CK_INVALID_HANDLE;
			clearCryptoBuffer(pSession);
		}

		if (rv == CKR_DEVICE_ERROR) {
			rv = handleDeviceError(hSession);
			FUNC_FAILS(rv, "Device error reported");
		}
	} else {
		if (pObject->C_Sign != NULL) {
			rv = pObject->C_Sign(pObject, &pSession->activeMechanism, pSession->cryptoBuffer, pSession->cryptoBufferSize, pSignature, pulSignatureLen);

			if ((pSignature != NULL) && (rv != CKR_BUFFER_TOO_SMALL)) {
				pSession->activeObjectHandle = CK_INVALID_HANDLE;
				clearCryptoBuffer(pSession);
			}

			if (rv == CKR_DEVICE_ERROR) {
				rv = handleDeviceError(hSession);
				FUNC_FAILS(rv, "Device error reported");
			}
		} else {
			FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
		}
	}

	FUNC_RETURNS(rv);
}

/*  C_SignRecoverInit initializes a signature operation, where the data
    can be recovered from the signature. */
CK_DECLARE_FUNCTION(CK_RV, C_SignRecoverInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hKey
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_SignRecover signs data in a single operation, where the data can be
    recovered from the signature. */
CK_DECLARE_FUNCTION(CK_RV, C_SignRecover)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pData,
		CK_ULONG ulDataLen,
		CK_BYTE_PTR pSignature,
		CK_ULONG_PTR pulSignatureLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_VerifyInit initializes a verification operation, where the signature is
    an appendix to the data. */
CK_DECLARE_FUNCTION(CK_RV, C_VerifyInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hKey
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if ((findSessionObject(pSession, hKey, &pObject) < 0) && (findObject(pSlot->token, hKey, &pObject, TRUE) < 0)) {
		FUNC_FAILS(CKR_KEY_HANDLE_INVALID, "Can not find key for handle");
	}

	if (pObject->C_VerifyInit != NULL) {
		rv = pObject->C_VerifyInit(pObject, pMechanism);
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported");
	}

	if (rv == CKR_OK) {
		pSession->activeObjectHandle = pObject->handle;
		rv = copyMechanismParameter(pSession, pMechanism);
	}

	FUNC_RETURNS(rv);
}

/*  C_Verify verifies a signature in a single-part operation, where the signature
    is an appendix to the data. */
CK_DECLARE_FUNCTION(CK_RV, C_Verify)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pData,
		CK_ULONG ulDataLen,
		CK_BYTE_PTR pSignature,
		CK_ULONG ulSignatureLen
)
{
	int rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (pSignature && !isValidPtr(pSignature)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if ((findSessionObject(pSession, pSession->activeObjectHandle, &pObject) < 0) && (findObject(pSlot->token, pSession->activeObjectHandle, &pObject, TRUE) < 0)) {
		FUNC_FAILS(CKR_KEY_HANDLE_INVALID, "Can not find key for handle");
	}

	if (pObject->C_Verify != NULL) {
		rv = pObject->C_Verify(pObject, &pSession->activeMechanism, pData, ulDataLen, pSignature, ulSignatureLen);
		pSession->activeObjectHandle = CK_INVALID_HANDLE;
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported");
	}

	FUNC_RETURNS(rv);
}

/*  C_VerifyUpdate continues a multiple-part verification operation,
    processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_VerifyUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pPart,
		CK_ULONG ulPartLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pPart)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if ((findSessionObject(pSession, pSession->activeObjectHandle, &pObject) < 0) && (findObject(pSlot->token, pSession->activeObjectHandle, &pObject, TRUE) < 0)) {
		FUNC_FAILS(CKR_KEY_HANDLE_INVALID, "Can not find key for handle");
	}

	if (pObject->C_VerifyUpdate != NULL) {
		rv = pObject->C_VerifyUpdate(pObject, &pSession->activeMechanism, pPart, ulPartLen);
	} else {
		rv = appendToCryptoBuffer(pSession, pPart, ulPartLen);
	}

	FUNC_RETURNS(rv);
}

/*  C_VerifyFinal finishes a multiple-part verification operation,
    checking the signature. */
CK_DECLARE_FUNCTION(CK_RV, C_VerifyFinal)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pSignature,
		CK_ULONG ulSignatureLen
)
{
	CK_RV rv;
	struct p11Object_t *pObject;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pSignature)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pSession->activeObjectHandle == CK_INVALID_HANDLE) {
		FUNC_FAILS(CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized");
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if ((findSessionObject(pSession, pSession->activeObjectHandle, &pObject) < 0) && (findObject(pSlot->token, pSession->activeObjectHandle, &pObject, TRUE) < 0)) {
		FUNC_FAILS(CKR_KEY_HANDLE_INVALID, "Can not find key for handle");
	}

	if (pObject->C_VerifyFinal != NULL) {
		rv = pObject->C_VerifyFinal(pObject, &pSession->activeMechanism, pSignature, ulSignatureLen);

		pSession->activeObjectHandle = CK_INVALID_HANDLE;
		clearCryptoBuffer(pSession);
	} else {
		if (pObject->C_Verify != NULL) {
			rv = pObject->C_Verify(pObject, &pSession->activeMechanism, pSession->cryptoBuffer, pSession->cryptoBufferSize, pSignature, ulSignatureLen);

			pSession->activeObjectHandle = CK_INVALID_HANDLE;
			clearCryptoBuffer(pSession);
		} else {
			FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported");
		}
	}

	FUNC_RETURNS(rv);
}

/*  C_VerifyRecoverInit initializes a signature verification operation,
    where the data is recovered from the signature. */
CK_DECLARE_FUNCTION(CK_RV, C_VerifyRecoverInit)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hKey
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_VerifyRecover verifies a signature in a single-part operation,
    where the data is recovered from the signature. */
CK_DECLARE_FUNCTION(CK_RV, C_VerifyRecover)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pSignature,
		CK_ULONG ulSignatureLen,
		CK_BYTE_PTR pData,
		CK_ULONG_PTR pulDataLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_DigestEncryptUpdate continues multiple-part digest and encryption
    operations, processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_DigestEncryptUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pPart,
		CK_ULONG ulPartLen,
		CK_BYTE_PTR pEncryptedPart,
		CK_ULONG_PTR pulEncryptedPartLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_DecryptDigestUpdate continues a multiple-part combined decryption and
    digest operation, processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_DecryptDigestUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pEncryptedPart,
		CK_ULONG ulEncryptedPartLen,
		CK_BYTE_PTR pPart,
		CK_ULONG_PTR pulPartLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_SignEncryptUpdate continues a multiple-part combined signature and
    encryption operation, processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_SignEncryptUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pPart,
		CK_ULONG ulPartLen,
		CK_BYTE_PTR pEncryptedPart,
		CK_ULONG_PTR pulEncryptedPartLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_DecryptVerifyUpdate continues a multiple-part combined decryption and verification
    operation, processing another data part. */
CK_DECLARE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pEncryptedPart,
		CK_ULONG ulEncryptedPartLen,
		CK_BYTE_PTR pPart,
		CK_ULONG_PTR pulPartLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_GenerateKey generates a secret key or set of domain parameters,
    creating a new object. */
CK_DECLARE_FUNCTION(CK_RV, C_GenerateKey)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_ATTRIBUTE_PTR pTemplate,
		CK_ULONG ulCount,
		CK_OBJECT_HANDLE_PTR phKey
)
{
	CK_RV rv;
	int pos;
	struct p11Slot_t *slot;
	struct p11Session_t *pSession;
	struct p11Token_t *token;
	struct p11Object_t *p11SecretKey;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pTemplate)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(phKey)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &slot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

#ifdef DEBUG
	debug("Secret Key Template\n");
	dumpAttributes(pTemplate, ulCount);
#endif

	pos = findAttributeInTemplate(CKA_TOKEN, pTemplate, ulCount);
	if (pos < 0) {
		FUNC_FAILS(CKR_TEMPLATE_INCOMPLETE, "CKA_TOKEN not found in secret key template");
	}

	rv = validateAttribute(&pTemplate[pos], sizeof(CK_BBOOL));
	if (rv != CKR_OK)
		FUNC_FAILS(rv, "CKA_TOKEN has invalid value");

	if (*(CK_BBOOL *)pTemplate[pos].pValue == 0) {
		FUNC_FAILS(CKR_TEMPLATE_INCONSISTENT, "Generating session key not supported");
	}

	rv = getValidatedToken(slot, &token);

	if (rv != CKR_OK) {
		return rv;
	}

	if (getSessionState(pSession, token) != CKS_RW_USER_FUNCTIONS) {
		FUNC_FAILS(CKR_SESSION_READ_ONLY, "Session is read/only");
	}

	rv = generateTokenKey(slot, pMechanism, pTemplate, ulCount, &p11SecretKey);

	if (rv == CKR_DEVICE_ERROR) {
		rv = handleDeviceError(hSession);
		FUNC_FAILS(rv, "Device error reported");
	}

	if (rv != CKR_OK) {
		FUNC_FAILS(rv, "Generating key pair on token failed");
	}

	*phKey = p11SecretKey->handle;

	FUNC_RETURNS(rv);
}

/*  C_GenerateKeyPair generates a public/private key pair, creating new key objects. */
CK_DECLARE_FUNCTION(CK_RV, C_GenerateKeyPair)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_ATTRIBUTE_PTR pPublicKeyTemplate,
		CK_ULONG ulPublicKeyAttributeCount,
		CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
		CK_ULONG ulPrivateKeyAttributeCount,
		CK_OBJECT_HANDLE_PTR phPublicKey,
		CK_OBJECT_HANDLE_PTR phPrivateKey
)
{
	CK_RV rv;
	int pos;
	struct p11Slot_t *slot;
	struct p11Session_t *pSession;
	struct p11Token_t *token;
	struct p11Object_t *p11PriKey, *p11PubKey;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pPublicKeyTemplate)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pPrivateKeyTemplate)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(phPublicKey)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(phPrivateKey)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &slot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

#ifdef DEBUG
	debug("Private Key Template\n");
	dumpAttributes(pPrivateKeyTemplate, ulPrivateKeyAttributeCount);
	debug("Public Key Template\n");
	dumpAttributes(pPublicKeyTemplate, ulPublicKeyAttributeCount);
#endif

	pos = findAttributeInTemplate(CKA_TOKEN, pPrivateKeyTemplate, ulPrivateKeyAttributeCount);
	if (pos < 0) {
		FUNC_FAILS(CKR_TEMPLATE_INCOMPLETE, "CKA_TOKEN not found in private key template");
	}

	rv = validateAttribute(&pPrivateKeyTemplate[pos], sizeof(CK_BBOOL));
	if (rv != CKR_OK)
		FUNC_FAILS(rv, "CKA_TOKEN has invalid value");

	if (*(CK_BBOOL *)pPrivateKeyTemplate[pos].pValue == 0) {
		FUNC_FAILS(CKR_TEMPLATE_INCONSISTENT, "Generating session key pairs not supported");
	}

	rv = getValidatedToken(slot, &token);

	if (rv != CKR_OK) {
		return rv;
	}

	if (getSessionState(pSession, token) != CKS_RW_USER_FUNCTIONS) {
		FUNC_FAILS(CKR_SESSION_READ_ONLY, "Session is read/only");
	}

	rv = generateTokenKeypair(slot, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &p11PubKey, &p11PriKey);

	if (rv == CKR_DEVICE_ERROR) {
		rv = handleDeviceError(hSession);
		FUNC_FAILS(rv, "Device error reported");
	}

	if (rv != CKR_OK) {
		FUNC_FAILS(rv, "Generating key pair on token failed");
	}

	*phPublicKey = p11PubKey->handle;
	*phPrivateKey = p11PriKey->handle;

	FUNC_RETURNS(rv);
}

/*  C_WrapKey wraps (i.e., encrypts) a private or secret key. */
CK_DECLARE_FUNCTION(CK_RV, C_WrapKey)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hWrappingKey,
		CK_OBJECT_HANDLE hKey,
		CK_BYTE_PTR pWrappedKey,
		CK_ULONG_PTR pulWrappedKeyLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_UnwrapKey unwraps (i.e. decrypts) a wrapped key, creating a new private key
    or secret key object. */
CK_DECLARE_FUNCTION(CK_RV, C_UnwrapKey)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hUnwrappingKey,
		CK_BYTE_PTR pWrappedKey,
		CK_ULONG ulWrappedKeyLen,
		CK_ATTRIBUTE_PTR pTemplate,
		CK_ULONG ulAttributeCount,
		CK_OBJECT_HANDLE_PTR phKey
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_DeriveKey derives a key from a base key, creating a new key object. */
CK_DECLARE_FUNCTION(CK_RV, C_DeriveKey)(
		CK_SESSION_HANDLE hSession,
		CK_MECHANISM_PTR pMechanism,
		CK_OBJECT_HANDLE hBaseKey,
		CK_ATTRIBUTE_PTR pTemplate,
		CK_ULONG ulAttributeCount,
		CK_OBJECT_HANDLE_PTR phKey
)
{
	CK_RV rv;
	struct p11Object_t *pObject, *derivedKey;
	struct p11Slot_t *pSlot;
	struct p11Session_t *pSession;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pMechanism)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(phKey)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	if (!isValidPtr(pTemplate)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &pSlot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlotKey(pSlot, hBaseKey, &pObject);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	if (pObject->C_DeriveKey != NULL) {
		rv = pObject->C_DeriveKey(pObject, pMechanism, pTemplate, ulAttributeCount, &derivedKey);
	} else {
		FUNC_FAILS(CKR_FUNCTION_NOT_SUPPORTED, "Operation not supported by token");
	}

	if (!derivedKey->tokenObj) {
		addSessionObject(pSession, derivedKey);
	}

	*phKey = derivedKey->handle;

	FUNC_RETURNS(rv);
}

/*  C_SeedRandom mixes additional seed material into the token�s random number generator. */
CK_DECLARE_FUNCTION(CK_RV, C_SeedRandom)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pSeed,
		CK_ULONG ulSeedLen
)
{
	CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(rv);
}

/*  C_GenerateRandom generates random or pseudo-random data. */
CK_DECLARE_FUNCTION(CK_RV, C_GenerateRandom)(
		CK_SESSION_HANDLE hSession,
		CK_BYTE_PTR pRandomData,
		CK_ULONG ulRandomLen
)
{
	CK_RV rv;
	struct p11Slot_t *slot;
	struct p11Session_t *pSession;
	struct p11Token_t *token;

	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	if (!isValidPtr(pRandomData)) {
		FUNC_FAILS(CKR_ARGUMENTS_BAD, "Invalid pointer argument");
	}

	rv = findSessionByHandle(&context->sessionPool, hSession, &pSession);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = findSlot(&context->slotPool, pSession->slotID, &slot);

	if (rv != CKR_OK) {
		FUNC_RETURNS(rv);
	}

	rv = getValidatedToken(slot, &token);

	if (rv != CKR_OK) {
		return rv;
	}

	rv = generateTokenRandom(slot, pRandomData, ulRandomLen);

	if (rv == CKR_DEVICE_ERROR) {
		rv = handleDeviceError(hSession);
		FUNC_FAILS(rv, "Device error reported");
	}

	if (rv != CKR_OK) {
		FUNC_FAILS(rv, "Generating random on token failed");
	}

	FUNC_RETURNS(rv);
}

/*  C_GetFunctionStatus obtained the status of a function
    running in parallel with an application. Now legacy! */
CK_DECLARE_FUNCTION(CK_RV, C_GetFunctionStatus)(
		CK_SESSION_HANDLE hSession
)
{
	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(CKR_FUNCTION_NOT_PARALLEL);
}

/*  C_CancelFunction cancelled a function running in parallel
    with an application. Now legacy! */
CK_DECLARE_FUNCTION(CK_RV, C_CancelFunction)(
		CK_SESSION_HANDLE hSession
)
{
	FUNC_CALLED();

	if (context == NULL) {
		FUNC_FAILS(CKR_CRYPTOKI_NOT_INITIALIZED, "C_Initialize not called");
	}

	FUNC_RETURNS(CKR_FUNCTION_NOT_PARALLEL);
}


text:
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Blurry-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/2192)
[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![Download](https://api.bintray.com/packages/wasabeef/maven/blurry/images/download.svg)](https://bintray.com/wasabeef/maven/blurry/_latestVersion)

`Blurry` is an easy blur library for `Android`.

![logo](art/blurry.png)

Screenshot
---

![Demo](art/blurry.gif)

How do I use it?
---

### Setup

##### Gradle
```groovy
dependencies {
    compile 'jp.wasabeef:blurry:0.0.3'
}
```

### Functions

**Overlay**

Parent must be ViewGroup

```java
Blurry.with(context).radius(25).sampling(2).onto(rootView);
```

**Into**
```java
Blurry.with(context).capture(view).into(imageView);
```

**Blur Options**

- Radius
- Down Sampling
- Color Filter
- Asynchronous Support

```java
Blurry.with(context)
  .radius(10)
  .sampling(8)
  .color(Color.argb(66, 255, 255, 0))
  .async()
  .onto(rootView);
```

Requirements
--------------
Android 2.3+

Developed By
-------
Daichi Furiya (Wasabeef) - <dadadada.chop@gmail.com>

License
-------

    Copyright 2015 Wasabeef

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.