. /lib/functions.sh . /lib/functions/uci-defaults.sh . /lib/functions/system.sh ramips_setup_interfaces() { local board="$1" case $board in aigale,ai-br100|\ alfa-network,ac1200rm|\ asus,rt-n12p|\ dlink,dwr-116-a1|\ dlink,dwr-921-c1|\ dlink,dwr-922-e2|\ dovado,tiny-ac|\ ohyeah,oy-0001|\ phicomm,psg1208|\ planex,db-wrt01|\ planex,mzk-750dhp|\ ralink,mt7620a-evb|\ ralink,mt7620a-mt7610e-evb|\ ralink,mt7620a-v22sg-evb|\ sanlinking,d240|\ zbtlink,zbt-ape522ii|\ zbtlink,zbt-we826-16m|\ zbtlink,zbt-we826-32m|\ zbtlink,zbt-we826-e|\ zbtlink,zbt-wr8305rt|\ zyxel,keenetic-omni) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0" ;; alfa-network,r36m-e4g|\ zbtlink,zbt-we1026-h-32m) ucidef_add_switch "switch0" \ "3:lan" "4:wan" "6@eth0" ;; alfa-network,tube-e4g|\ buffalo,wmr-300|\ dlink,dch-m225|\ edimax,ew-7476rpc|\ edimax,ew-7478ac|\ elecom,wrh-300cr|\ hootoo,ht-tm05|\ kimax,u25awf-h1|\ kimax,u35wf|\ kingston,mlw221|\ kingston,mlwg2|\ microduino,microwrt|\ netgear,ex2700|\ netgear,ex3700|\ netgear,ex6120|\ netgear,ex6130|\ netgear,wn3000rp-v3|\ planex,cs-qr10|\ planex,mzk-ex300np|\ planex,mzk-ex750np|\ ravpower,rp-wd03|\ sercomm,na930|\ tplink,re200-v1|\ tplink,re210-v1|\ yukai,bocco|\ zbtlink,zbt-cpe102|\ zte,q7) ucidef_add_switch "switch0" ucidef_add_switch_attr "switch0" "enable" "false" ucidef_set_interface_lan "eth0" ;; asus,rp-n53) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "6t@eth0" ;; asus,rt-ac51u|\ asus,rt-ac54u|\ asus,rt-n14u|\ bdcom,wap2100-sk|\ edimax,ew-7478apc|\ glinet,gl-mt300a|\ glinet,gl-mt300n|\ glinet,gl-mt750|\ hiwifi,hc5661|\ wrtnode,wrtnode|\ zbtlink,zbt-wa05|\ zyxel,keenetic-omni-ii) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "6@eth0" ;; buffalo,whr-300hp2|\ buffalo,whr-600d) ucidef_add_switch "switch0" \ "0:lan:1" "1:lan:2" "2:lan:3" "3:lan:4" "4:wan:5" "6@eth0" ;; buffalo,whr-1166d) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "5:wan" "6@eth0" ;; comfast,cf-wr800n|\ hnet,c108) ucidef_add_switch "switch0" \ "4:lan" "6@eth0" ;; dlink,dir-510l) ucidef_add_switch "switch0" \ "0:lan" "6@eth0" ;; dlink,dir-810l|\ netgear,jwnr2010-v5|\ phicomm,psg1218a|\ trendnet,tew-810dr|\ zbtlink,zbt-we2026) ucidef_add_switch "switch0" \ "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "4:wan" "6@eth0" ;; dlink,dwr-118-a1) ucidef_add_switch "switch0" \ "1:lan:2" "2:lan:3" "3:lan:1" "4:lan:0" "5:wan" "6@eth0" ;; dlink,dwr-118-a2) ucidef_add_switch "switch0" \ "1:lan:2" "2:lan:1" "3:lan:3" "4:lan" "0:wan" "6@eth0" ;; dlink,dwr-960) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "5:lan" "0:wan" "6@eth0" ;; edimax,br-6478ac-v2|\ lb-link,bl-w1200|\ tplink,archer-c2-v1) ucidef_add_switch "switch0" ucidef_add_switch_attr "switch0" "enable" "false" ucidef_add_switch "switch1" \ "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "6@eth0" ;; engenius,esr600) ucidef_add_switch "switch0" \ "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan" "0@eth0" ucidef_add_switch "switch1" \ "5:lan" "6@eth0" ucidef_add_switch_attr "switch1" "enable" "false" ;; fon,fon2601) ucidef_add_switch "switch0" \ "0:lan" "4:wan" "6@eth0" ;; head-weblink,hdrm200) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "5:lan" "0:wan" "6@eth0" ;; hiwifi,hc5761) ucidef_add_switch "switch0" \ "1:lan" "4:lan" "0:wan" "6@eth0" ;; hiwifi,hc5861) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "5:wan" "6@eth0" ;; iodata,wn-ac1167gr|\ iodata,wn-ac733gr3|\ iptime,a1004ns) ucidef_add_switch "switch0" ucidef_add_switch_attr "switch0" "enable" "false" ucidef_add_switch "switch1" \ "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "0:wan" "6@eth0" ;; iptime,a104ns) ucidef_add_switch "switch0" \ "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "0:wan" "6@eth0" ;; lava,lr-25g001) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" "0@eth0" ucidef_add_switch "switch1" \ "5:lan" "6@eth0" ucidef_add_switch_attr "switch1" "enable" "false" ;; lenovo,newifi-y1|\ xiaomi,miwifi-mini) ucidef_add_switch "switch0" \ "0:lan:2" "1:lan:1" "4:wan" "6@eth0" ;; lenovo,newifi-y1s) ucidef_add_switch "switch0" \ "1:lan:4" "2:lan:3" "4:lan:2" "5:lan:1" "0:wan" "6@eth0" ;; linksys,e1700|\ netis,wf2770|\ ralink,mt7620a-mt7530-evb) ucidef_add_switch "switch0" ucidef_add_switch_attr "switch0" "enable" "false" ucidef_add_switch "switch1" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0" ;; nexx,wt3020-4m|\ nexx,wt3020-8m) ucidef_add_switch "switch0" \ "4:lan" "0:wan" "6@eth0" ;; phicomm,k2g|\ wavlink,wl-wn530hg4) ucidef_add_switch "switch0" \ "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5:wan" "6@eth0" ;; phicomm,psg1218b) ucidef_add_switch "switch0" \ "0:lan:3" "1:lan:2" "2:lan:1" "3:wan" "6@eth0" ;; tplink,archer-c20i|\ tplink,archer-c20-v1|\ tplink,archer-c50-v1) ucidef_add_switch "switch0" \ "1:lan:3" "2:lan:4" "3:lan:1" "4:lan:2" "0:wan" "6@eth0" ;; tplink,archer-mr200) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "6t@eth0" ucidef_set_interface_wan "usb0" ;; vonets,var11n-300) ucidef_add_switch "switch0" \ "0:lan" "4:wan" "6@eth0" ;; wavlink,wl-wn579x3) ucidef_add_switch "switch0" \ "5:lan" "4:wan" "6@eth0" ;; youku,yk-l1|\ youku,yk-l1c) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "4:wan" "6@eth0" ;; zbtlink,zbt-we1026-5g-16m) ucidef_add_switch "switch0" \ "0:lan" "6t@eth0" ;; zyxel,keenetic-viva) ucidef_add_switch "switch1" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "7t@eth0" ;; esac } ramips_setup_macs() { local board="$1" local lan_mac="" local wan_mac="" local label_mac="" case $board in aigale,ai-br100|\ asus,rt-n12p|\ asus,rt-n14u|\ bdcom,wap2100-sk|\ edimax,ew-7478apc|\ fon,fon2601|\ head-weblink,hdrm200|\ netgear,jwnr2010-v5|\ nexx,wt3020-4m|\ nexx,wt3020-8m|\ phicomm,psg1208|\ planex,db-wrt01|\ planex,mzk-750dhp|\ sanlinking,d240|\ vonets,var11n-300|\ wrtnode,wrtnode|\ zbtlink,zbt-ape522ii|\ zbtlink,zbt-wa05|\ zbtlink,zbt-we2026|\ zbtlink,zbt-we826-16m|\ zbtlink,zbt-we826-32m|\ zbtlink,zbt-we826-e|\ zbtlink,zbt-wr8305rt) wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x4)" 1) ;; alfa-network,ac1200rm|\ dlink,dir-810l|\ trendnet,tew-810dr) wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x28)" 1) ;; alfa-network,r36m-e4g|\ zbtlink,zbt-we1026-h-32m) wan_mac=$(mtd_get_mac_binary factory 0x2e) label_mac=$(mtd_get_mac_binary factory 0x4) ;; asus,rt-ac51u|\ asus,rt-ac54u) lan_mac=$(mtd_get_mac_binary factory 0x22) ;; dlink,dch-m225) lan_mac=$(mtd_get_mac_ascii factory lanmac) ;; dlink,dir-510l|\ dlink,dwr-116-a1|\ dlink,dwr-118-a1|\ dlink,dwr-118-a2|\ dlink,dwr-921-c1|\ dlink,dwr-922-e2|\ dlink,dwr-960|\ lava,lr-25g001) wan_mac=$(jboot_config_read -m -i $(find_mtd_part "config") -o 0xE000) lan_mac=$(macaddr_add "$wan_mac" 1) label_mac=$wan_mac ;; dovado,tiny-ac) lan_mac=$(mtd_get_mac_ascii u-boot-env LAN_MAC_ADDR) wan_mac=$(mtd_get_mac_ascii u-boot-env WAN_MAC_ADDR) ;; edimax,br-6478ac-v2) wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x4)" 2) ;; engenius,esr600) lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) wan_mac=$(mtd_get_mac_ascii u-boot-env wanaddr) ;; glinet,gl-mt300a|\ glinet,gl-mt300n|\ glinet,gl-mt750) wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x4000)" 1) label_mac=$(mtd_get_mac_binary factory 0x4) ;; hiwifi,hc5661|\ hiwifi,hc5761|\ hiwifi,hc5861) lan_mac=$(mtd_get_mac_ascii bdinfo "Vfac_mac ") label_mac=$lan_mac [ -n "$lan_mac" ] || lan_mac=$(cat /sys/class/net/eth0/address) wan_mac=$(macaddr_add "$lan_mac" 1) ;; iodata,wn-ac1167gr|\ iodata,wn-ac733gr3) wan_mac=$(mtd_get_mac_ascii u-boot-env wanaddr) ;; iptime,a1004ns) wan_mac=$(mtd_get_mac_binary u-boot 0x1fc40) ;; iptime,a104ns) wan_mac=$(macaddr_add "$(mtd_get_mac_binary u-boot 0x1fc20)" 2) ;; lb-link,bl-w1200|\ phicomm,k2g|\ phicomm,psg1218a|\ phicomm,psg1218b) wan_mac=$(mtd_get_mac_binary factory 0x2e) label_mac=$wan_mac ;; lenovo,newifi-y1|\ lenovo,newifi-y1s|\ ohyeah,oy-0001|\ wavlink,wl-wn530hg4|\ youku,yk-l1|\ youku,yk-l1c) wan_mac=$(mtd_get_mac_binary factory 0x2e) ;; linksys,e1700) wan_mac=$(mtd_get_mac_ascii config WAN_MAC_ADDR) ;; netis,wf2770) wan_mac=$(mtd_get_mac_binary factory 0x2e) label_mac=$wan_mac ;; tplink,archer-c2-v1|\ tplink,archer-c20-v1|\ tplink,archer-c20i|\ tplink,archer-c50-v1|\ tplink,archer-mr200) wan_mac=$(macaddr_add "$(mtd_get_mac_binary rom 0xf100)" 1) ;; zbtlink,zbt-we1026-5g-16m) label_mac=$(mtd_get_mac_binary factory 0x4) ;; zyxel,keenetic-omni|\ zyxel,keenetic-omni-ii|\ zyxel,keenetic-viva) wan_mac=$(mtd_get_mac_binary factory 0x28) ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac [ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac } board_config_update board=$(board_name) ramips_setup_interfaces $board ramips_setup_macs $board board_config_flush exit 0 f='#n178'>178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio

    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.
*/

#include "hal.h"

/* Virtual serial port over USB.*/
SerialUSBDriver SDU1;

/*
 * Endpoints to be used for USBD1.
 */
#define USBD1_DATA_REQUEST_EP           1
#define USBD1_DATA_AVAILABLE_EP         1
#define USBD1_INTERRUPT_REQUEST_EP      2

/*
 * USB Device Descriptor.
 */
static const uint8_t vcom_device_descriptor_data[18] = {
  USB_DESC_DEVICE       (0x0110,        /* bcdUSB (1.1).                    */
                         0x02,          /* bDeviceClass (CDC).              */
                         0x00,          /* bDeviceSubClass.                 */
                         0x00,          /* bDeviceProtocol.                 */
                         0x40,          /* bMaxPacketSize.                  */
                         0x0483,        /* idVendor (ST).                   */
                         0x5740,        /* idProduct.                       */
                         0x0200,        /* bcdDevice.                       */
                         1,             /* iManufacturer.                   */
                         2,             /* iProduct.                        */
                         3,             /* iSerialNumber.                   */
                         1)             /* bNumConfigurations.              */
};

/*
 * Device Descriptor wrapper.
 */
static const USBDescriptor vcom_device_descriptor = {
  sizeof vcom_device_descriptor_data,
  vcom_device_descriptor_data
};

/* Configuration Descriptor tree for a CDC.*/
static const uint8_t vcom_configuration_descriptor_data[67] = {
  /* Configuration Descriptor.*/
  USB_DESC_CONFIGURATION(67,            /* wTotalLength.                    */
                         0x02,          /* bNumInterfaces.                  */
                         0x01,          /* bConfigurationValue.             */
                         0,             /* iConfiguration.                  */
                         0xC0,          /* bmAttributes (self powered).     */
                         50),           /* bMaxPower (100mA).               */
  /* Interface Descriptor.*/
  USB_DESC_INTERFACE    (0x00,          /* bInterfaceNumber.                */
                         0x00,          /* bAlternateSetting.               */
                         0x01,          /* bNumEndpoints.                   */
                         0x02,          /* bInterfaceClass (Communications
                                           Interface Class, CDC section
                                           4.2).                            */
                         0x02,          /* bInterfaceSubClass (Abstract
                                         Control Model, CDC section 4.3).   */
                         0x01,          /* bInterfaceProtocol (AT commands,
                                           CDC section 4.4).                */
                         0),            /* iInterface.                      */
  /* Header Functional Descriptor (CDC section 5.2.3).*/
  USB_DESC_BYTE         (5),            /* bLength.                         */
  USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
  USB_DESC_BYTE         (0x00),         /* bDescriptorSubtype (Header
                                           Functional Descriptor.           */
  USB_DESC_BCD          (0x0110),       /* bcdCDC.                          */
  /* Call Management Functional Descriptor. */
  USB_DESC_BYTE         (5),            /* bFunctionLength.                 */
  USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
  USB_DESC_BYTE         (0x01),         /* bDescriptorSubtype (Call Management
                                           Functional Descriptor).          */
  USB_DESC_BYTE         (0x00),         /* bmCapabilities (D0+D1).          */
  USB_DESC_BYTE         (0x01),         /* bDataInterface.                  */
  /* ACM Functional Descriptor.*/
  USB_DESC_BYTE         (4),            /* bFunctionLength.                 */
  USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
  USB_DESC_BYTE         (0x02),         /* bDescriptorSubtype (Abstract
                                           Control Management Descriptor).  */
  USB_DESC_BYTE         (0x02),         /* bmCapabilities.                  */
  /* Union Functional Descriptor.*/
  USB_DESC_BYTE         (5),            /* bFunctionLength.                 */
  USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
  USB_DESC_BYTE         (0x06),         /* bDescriptorSubtype (Union
                                           Functional Descriptor).          */
  USB_DESC_BYTE         (0x00),         /* bMasterInterface (Communication
                                           Class Interface).                */
  USB_DESC_BYTE         (0x01),         /* bSlaveInterface0 (Data Class
                                           Interface).                      */
  /* Endpoint 2 Descriptor.*/
  USB_DESC_ENDPOINT     (USBD1_INTERRUPT_REQUEST_EP|0x80,
                         0x03,          /* bmAttributes (Interrupt).        */
                         0x0008,        /* wMaxPacketSize.                  */
                         0xFF),         /* bInterval.                       */
  /* Interface Descriptor.*/
  USB_DESC_INTERFACE    (0x01,          /* bInterfaceNumber.                */
                         0x00,          /* bAlternateSetting.               */
                         0x02,          /* bNumEndpoints.                   */
                         0x0A,          /* bInterfaceClass (Data Class
                                           Interface, CDC section 4.5).     */
                         0x00,          /* bInterfaceSubClass (CDC section
                                           4.6).                            */
                         0x00,          /* bInterfaceProtocol (CDC section
                                           4.7).                            */
                         0x00),         /* iInterface.                      */
  /* Endpoint 3 Descriptor.*/
  USB_DESC_ENDPOINT     (USBD1_DATA_AVAILABLE_EP,       /* bEndpointAddress.*/
                         0x02,          /* bmAttributes (Bulk).             */
                         0x0040,        /* wMaxPacketSize.                  */
                         0x00),         /* bInterval.                       */
  /* Endpoint 1 Descriptor.*/
  USB_DESC_ENDPOINT     (USBD1_DATA_REQUEST_EP|0x80,    /* bEndpointAddress.*/
                         0x02,          /* bmAttributes (Bulk).             */
                         0x0040,        /* wMaxPacketSize.                  */
                         0x00)          /* bInterval.                       */
};

/*
 * Configuration Descriptor wrapper.
 */
static const USBDescriptor vcom_configuration_descriptor = {
  sizeof vcom_configuration_descriptor_data,
  vcom_configuration_descriptor_data
};

/*
 * U.S. English language identifier.
 */
static const uint8_t vcom_string0[] = {
  USB_DESC_BYTE(4),                     /* bLength.                         */
  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
  USB_DESC_WORD(0x0409)                 /* wLANGID (U.S. English).          */
};

/*
 * Vendor string.
 */
static const uint8_t vcom_string1[] = {
  USB_DESC_BYTE(38),                    /* bLength.                         */
  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
  'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
  'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
  'c', 0, 's', 0
};

/*
 * Device Description string.
 */
static const uint8_t vcom_string2[] = {
  USB_DESC_BYTE(56),                    /* bLength.                         */
  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
  'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0,
  'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0,
  'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0,
  'o', 0, 'r', 0, 't', 0
};

/*
 * Serial Number string.
 */
static const uint8_t vcom_string3[] = {
  USB_DESC_BYTE(8),                     /* bLength.                         */
  USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
  '0' + CH_KERNEL_MAJOR, 0,
  '0' + CH_KERNEL_MINOR, 0,
  '0' + CH_KERNEL_PATCH, 0
};

/*
 * Strings wrappers array.
 */
static const USBDescriptor vcom_strings[] = {
  {sizeof vcom_string0, vcom_string0},
  {sizeof vcom_string1, vcom_string1},
  {sizeof vcom_string2, vcom_string2},
  {sizeof vcom_string3, vcom_string3}
};

/*
 * Handles the GET_DESCRIPTOR callback. All required descriptors must be
 * handled here.
 */
static const USBDescriptor *get_descriptor(USBDriver *usbp,
                                           uint8_t dtype,
                                           uint8_t dindex,
                                           uint16_t lang) {

  (void)usbp;
  (void)lang;
  switch (dtype) {
  case USB_DESCRIPTOR_DEVICE:
    return &vcom_device_descriptor;
  case USB_DESCRIPTOR_CONFIGURATION:
    return &vcom_configuration_descriptor;
  case USB_DESCRIPTOR_STRING:
    if (dindex < 4)
      return &vcom_strings[dindex];
  }
  return NULL;
}

/**
 * @brief   IN EP1 state.
 */
static USBInEndpointState ep1instate;

/**
 * @brief   OUT EP1 state.
 */
static USBOutEndpointState ep1outstate;

/**
 * @brief   EP1 initialization structure (both IN and OUT).
 */
static const USBEndpointConfig ep1config = {
  USB_EP_MODE_TYPE_BULK,
  NULL,
  sduDataTransmitted,
  sduDataReceived,
  0x0040,
  0x0040,
  &ep1instate,
  &ep1outstate,
  2,
  NULL
};

/**
 * @brief   IN EP2 state.
 */
static USBInEndpointState ep2instate;

/**
 * @brief   EP2 initialization structure (IN only).
 */
static const USBEndpointConfig ep2config = {
  USB_EP_MODE_TYPE_INTR,
  NULL,
  sduInterruptTransmitted,
  NULL,
  0x0010,
  0x0000,
  &ep2instate,
  NULL,
  1,
  NULL
};

/*
 * Handles the USB driver global events.
 */
static void usb_event(USBDriver *usbp, usbevent_t event) {
  extern SerialUSBDriver SDU1;

  switch (event) {
  case USB_EVENT_ADDRESS:
    return;
  case USB_EVENT_CONFIGURED:
    chSysLockFromISR();

    /* Enables the endpoints specified into the configuration.
       Note, this callback is invoked from an ISR so I-Class functions
       must be used.*/
    usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config);
    usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config);

    /* Resetting the state of the CDC subsystem.*/
    sduConfigureHookI(&SDU1);

    chSysUnlockFromISR();
    return;
  case USB_EVENT_RESET:
    /* Falls into.*/
  case USB_EVENT_UNCONFIGURED:
    /* Falls into.*/
  case USB_EVENT_SUSPEND:
    chSysLockFromISR();

    /* Disconnection event on suspend.*/
    sduSuspendHookI(&SDU1);

    chSysUnlockFromISR();
    return;
  case USB_EVENT_WAKEUP:
    chSysLockFromISR();

    /* Disconnection event on suspend.*/
    sduWakeupHookI(&SDU1);

    chSysUnlockFromISR();
    return;
  case USB_EVENT_STALLED:
    return;
  }
  return;
}

/*
 * Handles the USB driver global events.
 */
static void sof_handler(USBDriver *usbp) {

  (void)usbp;

  osalSysLockFromISR();
  sduSOFHookI(&SDU1);
  osalSysUnlockFromISR();
}

/*
 * USB driver configuration.
 */
const USBConfig usbcfg = {
  usb_event,
  get_descriptor,
  sduRequestsHook,
  sof_handler
};

/*
 * Serial over USB driver configuration.
 */
const SerialUSBConfig serusbcfg = {
  &USBD1,
  USBD1_DATA_REQUEST_EP,
  USBD1_DATA_AVAILABLE_EP,
  USBD1_INTERRUPT_REQUEST_EP
};