<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13997">View Change</a></p><div style="white-space:pre-wrap"></div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add a new (skeleton of a) USB CCID class driver<br><br>This tries to implement a USB CCID (Chip Card Interface Device) Class<br>core driver in "ASF4 style".  Code is currently mainly untested.<br><br>Change-Id: Ia4d8a6cdc3de26fdc83dcbf89db894b513915a9a<br>---<br>M sysmoOCTSIM/gcc/Makefile<br>A sysmoOCTSIM/usb/class/ccid/device/ccid_df.c<br>A sysmoOCTSIM/usb/class/ccid/device/ccid_df.h<br>3 files changed, 314 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile</span><br><span>index 2dba3e3..080aa41 100644</span><br><span>--- a/sysmoOCTSIM/gcc/Makefile</span><br><span>+++ b/sysmoOCTSIM/gcc/Makefile</span><br><span>@@ -2,6 +2,8 @@</span><br><span> # Automatically-generated file. Do not edit!</span><br><span> ################################################################################</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+EXTRA_CFLAGS=-I/usr/local/arm-none-eabi/include -I../../ccid</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> ifdef SystemRoot</span><br><span>     SHELL = cmd.exe</span><br><span>      MK_DIR = mkdir</span><br><span>@@ -35,6 +37,7 @@</span><br><span> usb \</span><br><span> hpl/dmac \</span><br><span> usb/class/cdc/device \</span><br><span style="color: hsl(120, 100%, 40%);">+usb/class/ccid/device \</span><br><span> stdio_redirect \</span><br><span> hal/utils/src \</span><br><span> hpl/usb \</span><br><span>@@ -56,6 +59,7 @@</span><br><span> hpl/core/hpl_core_m4.o \</span><br><span> hal/src/hal_cache.o \</span><br><span> usb/class/cdc/device/cdcdf_acm.o \</span><br><span style="color: hsl(120, 100%, 40%);">+usb/class/ccid/device/ccid_df.o \</span><br><span> hal/utils/src/utils_syscalls.o \</span><br><span> stdio_redirect/gcc/read.o \</span><br><span> gcc/system_same54.o \</span><br><span>@@ -107,6 +111,7 @@</span><br><span> "hpl/core/hpl_core_m4.o" \</span><br><span> "hal/src/hal_cache.o" \</span><br><span> "usb/class/cdc/device/cdcdf_acm.o" \</span><br><span style="color: hsl(120, 100%, 40%);">+"usb/class/ccid/device/ccid_df.o" \</span><br><span> "hal/utils/src/utils_syscalls.o" \</span><br><span> "stdio_redirect/gcc/read.o" \</span><br><span> "gcc/system_same54.o" \</span><br><span>@@ -250,7 +255,7 @@</span><br><span>     @echo ARM/GNU C Compiler</span><br><span>     $(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \</span><br><span> -D__SAME54N19A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \</span><br><span style="color: hsl(0, 100%, 40%);">--I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../config" -I"../stdio_redirect" -I"../" -I"../dma_m2m" -I"../" -I"../CMSIS/Core/Include" -I"../include"  \</span><br><span style="color: hsl(120, 100%, 40%);">+-I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/class/ccid" -I"../usb/class/ccid/device" -I"../usb/device" -I"../" -I"../config" -I"../stdio_redirect" -I"../" -I"../dma_m2m" -I"../" -I"../CMSIS/Core/Include" -I"../include"  \</span><br><span> -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"</span><br><span>         @echo Finished building: $<</span><br><span> </span><br><span>@@ -259,7 +264,7 @@</span><br><span>     @echo ARM/GNU Assembler</span><br><span>      $(QUOTE)arm-none-eabi-as$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \</span><br><span> -D__SAME54N19A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \</span><br><span style="color: hsl(0, 100%, 40%);">--I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../config" -I"../stdio_redirect" -I"../" -I"../dma_m2m" -I"../" -I"../CMSIS/Core/Include" -I"../include"  \</span><br><span style="color: hsl(120, 100%, 40%);">+-I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/class/ccid" -I"../usb/class/ccid/device" -I"../usb/device" -I"../" -I"../config" -I"../stdio_redirect" -I"../" -I"../dma_m2m" -I"../" -I"../CMSIS/Core/Include" -I"../include"  \</span><br><span> -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"</span><br><span>  @echo Finished building: $<</span><br><span> </span><br><span>@@ -268,7 +273,7 @@</span><br><span>     @echo ARM/GNU Preprocessing Assembler</span><br><span>        $(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \</span><br><span> -D__SAME54N19A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \</span><br><span style="color: hsl(0, 100%, 40%);">--I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../config" -I"../stdio_redirect" -I"../" -I"../dma_m2m" -I"../" -I"../CMSIS/Core/Include" -I"../include"  \</span><br><span style="color: hsl(120, 100%, 40%);">+-I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/class/ccid" -I"../usb/class/ccid/device" -I"../usb/device" -I"../" -I"../config" -I"../stdio_redirect" -I"../" -I"../dma_m2m" -I"../" -I"../CMSIS/Core/Include" -I"../include"  \</span><br><span> -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"</span><br><span>         @echo Finished building: $<</span><br><span> </span><br><span>diff --git a/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c b/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c</span><br><span>new file mode 100644</span><br><span>index 0000000..018208a</span><br><span>--- /dev/null</span><br><span>+++ b/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c</span><br><span>@@ -0,0 +1,289 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief USB Device Stack CCID Function Implementation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyroght (c) 2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This library is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU Lesser General Public</span><br><span style="color: hsl(120, 100%, 40%);">+ * License as published by the Free Software Foundation; either</span><br><span style="color: hsl(120, 100%, 40%);">+ * version 2.1 of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This library is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><br><span style="color: hsl(120, 100%, 40%);">+ * Lesser General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Lesser General Public</span><br><span style="color: hsl(120, 100%, 40%);">+ * License along with this library; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "ccid_df.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "ccid_proto.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "usb_includes.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef USB_CLASS_CCID</span><br><span style="color: hsl(120, 100%, 40%);">+#define        USB_CLASS_CCID  11</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ccid_df_func_data {</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t func_iface;     /*!< interface number */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t func_ep_in;     /*!< IN endpoint number */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t func_ep_out;    /*!< OUT endpoint number */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t func_ep_irq;    /*!< IRQ endpoint number */</span><br><span style="color: hsl(120, 100%, 40%);">+        bool enabled;           /*!< is this driver/function enabled? */</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct usb_ccid_class_descriptor *ccid_cd;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct usbdf_driver _ccid_df;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ccid_df_func_data _ccid_df_funcd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* FIXME: make those configurable, ensure they're sized according to</span><br><span style="color: hsl(120, 100%, 40%);">+ * bNumClockSupported / bNumDataRatesSupported */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t ccid_clock_frequencies[] = { LE32(20000) };</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t ccid_baud_rates[] = { LE32(9600) };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ccid_df_func_data *func_data = (struct ccid_df_func_data *)(drv->func_data);</span><br><span style="color: hsl(120, 100%, 40%);">+        usb_iface_desc_t ifc_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *ifc, *ep;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ifc = desc->sod;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* FIXME: iterate over multiple interfaces? */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ifc)</span><br><span style="color: hsl(120, 100%, 40%);">+             return ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ifc_desc.bInterfaceNumber = ifc[2];</span><br><span style="color: hsl(120, 100%, 40%);">+   ifc_desc.bInterfaceClass = ifc[5];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ifc_desc.bInterfaceClass != USB_CLASS_CCID)</span><br><span style="color: hsl(120, 100%, 40%);">+               return ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (func_data->func_iface == ifc_desc.bInterfaceNumber)</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_ALREADY_INITIALIZED;</span><br><span style="color: hsl(120, 100%, 40%);">+       else if (func_data->func_iface != 0xff)</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_NO_RESOURCE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     func_data->func_iface = ifc_desc.bInterfaceNumber;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ep = usb_find_desc(ifc, desc->eod, USB_DT_ENDPOINT);</span><br><span style="color: hsl(120, 100%, 40%);">+       while (NULL != ep) {</span><br><span style="color: hsl(120, 100%, 40%);">+          usb_ep_desc_t ep_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+                ep_desc.bEndpointAddress = ep[2];</span><br><span style="color: hsl(120, 100%, 40%);">+             ep_desc.bmAttributes = ep[3];</span><br><span style="color: hsl(120, 100%, 40%);">+         ep_desc.wMaxPacketSize = usb_get_u16(ep + 4);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (usb_d_ep_init(ep_desc.bEndpointAddress, ep_desc.bmAttributes, ep_desc.wMaxPacketSize))</span><br><span style="color: hsl(120, 100%, 40%);">+                    return ERR_NOT_INITIALIZED;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ep_desc.bEndpointAddress & USB_EP_DIR_IN) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if ((ep_desc.bmAttributes & USB_EP_XTYPE_MASK) == USB_EP_XTYPE_INTERRUPT)</span><br><span style="color: hsl(120, 100%, 40%);">+                         func_data->func_ep_irq = ep_desc.bEndpointAddress;</span><br><span style="color: hsl(120, 100%, 40%);">+                 else</span><br><span style="color: hsl(120, 100%, 40%);">+                          func_data->func_ep_in = ep_desc.bEndpointAddress;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      func_data->func_ep_out = ep_desc.bEndpointAddress;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             usb_d_ep_enable(ep_desc.bEndpointAddress);</span><br><span style="color: hsl(120, 100%, 40%);">+            desc->sod = ep;</span><br><span style="color: hsl(120, 100%, 40%);">+            ep = usb_find_ep_desc(usb_desc_next(desc->sod), desc->eod);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ASSERT(func_data->func_ep_irq);</span><br><span style="color: hsl(120, 100%, 40%);">+    ASSERT(func_data->func_ep_in);</span><br><span style="color: hsl(120, 100%, 40%);">+     ASSERT(func_data->func_ep_out);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  _ccid_df_funcd.enabled = true;</span><br><span style="color: hsl(120, 100%, 40%);">+        return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_disable(struct usbdf_driver *drv, struct usbd_descriptors *desc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ccid_df_func_data *func_data = (struct ccid_df_func_data *)(drv->func_data);</span><br><span style="color: hsl(120, 100%, 40%);">+        usb_iface_desc_t ifc_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (desc) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ifc_desc.bInterfaceClass = desc->sod[5];</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ifc_desc.bInterfaceClass != USB_CLASS_CCID)</span><br><span style="color: hsl(120, 100%, 40%);">+                       return ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   func_data->func_iface = 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (func_data->func_ep_in != 0xff) {</span><br><span style="color: hsl(120, 100%, 40%);">+               func_data->func_ep_in = 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+              usb_d_ep_deinit(func_data->func_ep_in);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (func_data->func_ep_out != 0xff) {</span><br><span style="color: hsl(120, 100%, 40%);">+              func_data->func_ep_out = 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+             usb_d_ep_deinit(func_data->func_ep_out);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (func_data->func_ep_irq != 0xff) {</span><br><span style="color: hsl(120, 100%, 40%);">+              func_data->func_ep_irq = 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+             usb_d_ep_deinit(func_data->func_ep_irq);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   _ccid_df_funcd.enabled = true;</span><br><span style="color: hsl(120, 100%, 40%);">+        return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief CCID Control Function (callback with USB core) */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_ctrl(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (ctrl) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case USBDF_ENABLE:</span><br><span style="color: hsl(120, 100%, 40%);">+            return ccid_df_enable(drv, (struct usbd_descriptors *)param);</span><br><span style="color: hsl(120, 100%, 40%);">+ case USBDF_DISABLE:</span><br><span style="color: hsl(120, 100%, 40%);">+           return ccid_df_disable(drv, (struct usbd_descriptors *)param);</span><br><span style="color: hsl(120, 100%, 40%);">+        case USBDF_GET_IFACE:</span><br><span style="color: hsl(120, 100%, 40%);">+         return ERR_UNSUPPORTED_OP;</span><br><span style="color: hsl(120, 100%, 40%);">+    default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Section 5.3.1: ABORT */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_ctrl_req_ccid_abort(uint8_t ep, struct usb_req *req,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          enum usb_ctrl_stage stage)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct usb_ccid_class_descriptor *ccid_cd = _ccid_df_funcd.ccid_cd;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t slot_nr = req->wValue & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (slot_nr > ccid_cd->bMaxSlotIndex)</span><br><span style="color: hsl(120, 100%, 40%);">+           return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       slot_nr = req->wValue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* FIXME: Implement Abort handling, particularly in combination with</span><br><span style="color: hsl(120, 100%, 40%);">+   * the PC_to_RDR_Abort on the OUT EP */</span><br><span style="color: hsl(120, 100%, 40%);">+       return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Section 5.3.2: return array of DWORD containing clock frequencies in kHz */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_ctrl_req_ccid_get_clock_freq(uint8_t ep, struct usb_req *req,</span><br><span style="color: hsl(120, 100%, 40%);">+                                               enum usb_ctrl_stage stage)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct usb_ccid_class_descriptor *ccid_cd = _ccid_df_funcd.ccid_cd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (stage != USB_DATA_STAGE)</span><br><span style="color: hsl(120, 100%, 40%);">+          return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (req->wLength != ccid_cd->bNumClockSupported * sizeof(uint32_t))</span><br><span style="color: hsl(120, 100%, 40%);">+             return ERR_INVALID_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return usbdc_xfer(ep, (uint8_t *)ccid_clock_frequencies, req->wLength, false);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Section 5.3.3: return array of DWORD containing data rates in bps */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_ctrl_req_ccid_get_data_rates(uint8_t ep, struct usb_req *req,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             enum usb_ctrl_stage stage)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct usb_ccid_class_descriptor *ccid_cd = _ccid_df_funcd.ccid_cd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (stage != USB_DATA_STAGE)</span><br><span style="color: hsl(120, 100%, 40%);">+          return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (req->wLength != ccid_cd->bNumDataRatesSupported * sizeof(uint32_t))</span><br><span style="color: hsl(120, 100%, 40%);">+         return ERR_INVALID_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return usbdc_xfer(ep, (uint8_t *)ccid_baud_rates, req->wLength, false);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* process a control endpoint request */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t ccid_df_ctrl_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   /* verify this is a class-specific request */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (0x01 != ((req->bmRequestType >> 5) & 0x03))</span><br><span style="color: hsl(120, 100%, 40%);">+                return ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Verify req->wIndex == interface */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (req->wIndex != _ccid_df_funcd.func_iface)</span><br><span style="color: hsl(120, 100%, 40%);">+                return ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (req->bRequest) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case CLASS_SPEC_CCID_ABORT:</span><br><span style="color: hsl(120, 100%, 40%);">+           if (req->bmRequestType & USB_EP_DIR_IN)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               return ccid_df_ctrl_req_ccid_abort(ep, req, stage);</span><br><span style="color: hsl(120, 100%, 40%);">+   case CLASS_SPEC_CCID_GET_CLOCK_FREQ:</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!(req->bmRequestType & USB_EP_DIR_IN))</span><br><span style="color: hsl(120, 100%, 40%);">+                     return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               return ccid_df_ctrl_req_ccid_get_clock_freq(ep, req, stage);</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLASS_SPEC_CCID_GET_DATA_RATES:</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!(req->bmRequestType & USB_EP_DIR_IN))</span><br><span style="color: hsl(120, 100%, 40%);">+                     return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               return ccid_df_ctrl_req_ccid_get_data_rates(ep, req, stage);</span><br><span style="color: hsl(120, 100%, 40%);">+  default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct usbdc_handler ccid_df_req_h = { NULL, (FUNC_PTR) ccid_df_ctrl_req };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (usbdc_get_state() > USBD_S_POWER)</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  _ccid_df.ctrl = ccid_df_ctrl;</span><br><span style="color: hsl(120, 100%, 40%);">+ _ccid_df.func_data = &_ccid_df_funcd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* register the actual USB Function */</span><br><span style="color: hsl(120, 100%, 40%);">+        usbdc_register_function(&_ccid_df);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* register the call-back for control endpoint handling */</span><br><span style="color: hsl(120, 100%, 40%);">+    usbdc_register_handler(USBDC_HDL_REQ, &ccid_df_req_h);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ccid_df_deinit(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   usb_d_ep_deinit(_ccid_df_funcd.func_ep_in);</span><br><span style="color: hsl(120, 100%, 40%);">+   usb_d_ep_deinit(_ccid_df_funcd.func_ep_out);</span><br><span style="color: hsl(120, 100%, 40%);">+  usb_d_ep_deinit(_ccid_df_funcd.func_ep_irq);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_read_out(uint8_t *buf, uint32_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ccid_df_is_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    return usbdc_xfer(_ccid_df_funcd.func_ep_out, buf, size, false);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_write_in(uint8_t *buf, uint32_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ccid_df_is_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    return usbdc_xfer(_ccid_df_funcd.func_ep_in, buf, size, true);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_write_irq(uint8_t *buf, uint32_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ccid_df_is_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    return usbdc_xfer(_ccid_df_funcd.func_ep_irq, buf, size, true);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_register_callback(enum ccid_df_cb_type cb_type, FUNC_PTR func)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (cb_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+    case CCID_DF_CB_READ_OUT:</span><br><span style="color: hsl(120, 100%, 40%);">+             usb_d_ep_register_callback(_ccid_df_funcd.func_ep_out, USB_D_EP_CB_XFER, func);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case CCID_DF_CB_WRITE_IN:</span><br><span style="color: hsl(120, 100%, 40%);">+             usb_d_ep_register_callback(_ccid_df_funcd.func_ep_in, USB_D_EP_CB_XFER, func);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case CCID_DF_CB_WRITE_IRQ:</span><br><span style="color: hsl(120, 100%, 40%);">+            usb_d_ep_register_callback(_ccid_df_funcd.func_ep_irq, USB_D_EP_CB_XFER, func);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool ccid_df_is_enabled(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return _ccid_df_funcd.enabled;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/sysmoOCTSIM/usb/class/ccid/device/ccid_df.h b/sysmoOCTSIM/usb/class/ccid/device/ccid_df.h</span><br><span>new file mode 100644</span><br><span>index 0000000..21fa99e</span><br><span>--- /dev/null</span><br><span>+++ b/sysmoOCTSIM/usb/class/ccid/device/ccid_df.h</span><br><span>@@ -0,0 +1,17 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "usbdc.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum ccid_df_cb_type {</span><br><span style="color: hsl(120, 100%, 40%);">+     CCID_DF_CB_READ_OUT,</span><br><span style="color: hsl(120, 100%, 40%);">+  CCID_DF_CB_WRITE_IN,</span><br><span style="color: hsl(120, 100%, 40%);">+  CCID_DF_CB_WRITE_IRQ,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_init(void);</span><br><span style="color: hsl(120, 100%, 40%);">+void ccid_df_deinit(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_read_out(uint8_t *buf, uint32_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_write_in(uint8_t *buf, uint32_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_write_irq(uint8_t *buf, uint32_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t ccid_df_register_callback(enum ccid_df_cb_type cb_type, FUNC_PTR ptr);</span><br><span style="color: hsl(120, 100%, 40%);">+bool ccid_df_is_enabled(void);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13997">change 13997</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13997"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ccid-firmware </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ia4d8a6cdc3de26fdc83dcbf89db894b513915a9a </div>
<div style="display:none"> Gerrit-Change-Number: 13997 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>