Цель статьи:

  • На примере добавления дополнительных классов USB (Media Transfer Protocol (MTP) и Smart Card (CCID)) показать каким образом можно вносить изменения в скрипты автогенерации для ускорения создания последующих проектов, а также для исправления существующих ошибок в них, чтобы не держать в голове, какие в каком случае постоянно вносить правки для исправления тех или иных ошибок.

  • Похожим образом править любые другие ошибки/добавлять функционал, вносить новые параметры

Введение

Иногда возникает необходимость добавить/исправить что-нибудь в скриптах автогенерации кода. В частности, понадобилось добавить шаблон для MTP класса USB. Оказалось, что реализация класса присутствует в репозитории HAL интересующего семейства F4, но глобально она оказалась выключена, несмотря на то, что класс был уже прописан. Странно то, что USB классы заявлены ST как независимые от семейства, но по факту - в библиотеках для каждого семейства они разные!

Исправляемые объекты

Для включения необходимо внести правки в:

  1. Базу данных устройств (stm32cube_db_vxx), в которой содержатся общие настройки, лежат по разным путям для CubeMX в linux обычно ("Путь до программы"/STM32CubeMX/db), в CubeIDE ("Путь до программы"/STM32CubeIDE/1.xx.x/plugins/com.st.stm32cube.common.mx_6.xx.0.xxxxxxxxxxxx/db). Также для совместимости со старыми проектами MX и IDE выкачивает базы в (~/.stm32cubemx/databases/DB.x.x.xx). Править или накладывать патч нужно ко всем, чтобы при открытии предыдущих проектов/разных сред автогенерация не ломалась.

  2. HAL библиотеки для конкретного семейства. В нашем случае для F4 (~/STM32Cube/Repository/STM32Cube_FW_F4_V1.28.0). Наличие ошибок в них уже классика)

Правки

Добавляем классы в базу данных устройств (пункт 1 выше). Эти правки общие для всех семейств STM32:

Скрытый текст
Date: Tue, 27 Aug 2024 19:31:28 +0300
Subject: [PATCH 1/2] Add USB MTP CCID

---
 mcu/IP/USB_DEVICE-v1.0_Cube_Modes.xml         | 28 +++++++++++++++++++
 mcu/IP/USB_DEVICE-v1.1_Cube_Modes.xml         | 28 +++++++++++++++++++
 mcu/IP/USB_DEVICE-v2.0_Cube_Modes.xml         | 11 ++++++--
 .../STMicroelectronics.USB_DEVICE.1.0.0.vpdsc | 12 ++++++++
 .../STMicroelectronics.USB_DEVICE.2.0.0.vpdsc | 12 ++++++++
 .../STMicroelectronics.USB_DEVICE.3.0.0.vpdsc | 12 ++++++++
 6 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/mcu/IP/USB_DEVICE-v1.0_Cube_Modes.xml b/mcu/IP/USB_DEVICE-v1.0_Cube_Modes.xml
index 7cee282..9e50dc9 100644
--- a/mcu/IP/USB_DEVICE-v1.0_Cube_Modes.xml
+++ b/mcu/IP/USB_DEVICE-v1.0_Cube_Modes.xml
@@ -2208,6 +2208,20 @@
 					<Semaphore>USB_DEVICE_MSC$context</Semaphore>
 					<Semaphore>MSC_HS$context</Semaphore>
 				</Mode>	
+				<Mode Name="CCID_HS" UserName="Smart Card Class (CCID)">
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_CCID_HS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_HIGH_SPEED</Semaphore>
+					<Semaphore>CCID_HS</Semaphore>
+				</Mode>
+				<Mode Name="MTP_HS" UserName="Media Transfer Protocol (MTP)">				
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_MTP_HS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_HIGH_SPEED</Semaphore>
+					<Semaphore>MTP_HS</Semaphore>
+				</Mode>	
 				<!-- Ticket 78428 New USB Classes Must wait -->
 				<!--
 				<Mode Name="BILLBOARD_HS" UserName="Bill Board Class" RemoveCondition="!(DIE419 | DIE421 | DIE434 | DIE413 | DIE423 | DIE463 | DIE441 | DIE431)">
@@ -2275,6 +2289,20 @@
 					<Semaphore>USB_DEVICE_MSC$context</Semaphore>
 					<Semaphore>MSC_FS$context</Semaphore>
 				</Mode>	
+				<Mode Name="CCID_FS" UserName="Smart Card Class (CCID)">
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_CCID_FS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_FULL_SPEED</Semaphore>
+					<Semaphore>CCID_FS</Semaphore>
+				</Mode>
+				<Mode Name="MTP_FS" UserName="Media Transfer Protocol (MTP)">				
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_MTP_FS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_FULL_SPEED</Semaphore>
+					<Semaphore>MTP_FS</Semaphore>
+				</Mode>
 				<!-- Ticket 78428 New USB Classes : Must wait -->
 				<!-- 
 				<Mode Name="BILLBOARD_FS" UserName="Bill Board Class" RemoveCondition="!(DIE419 | DIE421 | DIE434 | DIE413 | DIE423 | DIE463 | DIE441 | DIE431)">
diff --git a/mcu/IP/USB_DEVICE-v1.1_Cube_Modes.xml b/mcu/IP/USB_DEVICE-v1.1_Cube_Modes.xml
index 57dfba9..91bc240 100644
--- a/mcu/IP/USB_DEVICE-v1.1_Cube_Modes.xml
+++ b/mcu/IP/USB_DEVICE-v1.1_Cube_Modes.xml
@@ -1994,6 +1994,20 @@
 					</SignalLogicalOp>
 					<Semaphore>USB_DEVICE_MSC</Semaphore>
 					<Semaphore>MSC_HS</Semaphore>
+				</Mode>
+				<Mode Name="CCID_HS" UserName="Smart Card Class (CCID)">
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_CCID_HS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_HIGH_SPEED</Semaphore>
+					<Semaphore>CCID_HS</Semaphore>
+				</Mode>
+				<Mode Name="MTP_HS" UserName="Media Transfer Protocol (MTP)">				
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_MTP_HS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_HIGH_SPEED</Semaphore>
+					<Semaphore>MTP_HS</Semaphore>
 				</Mode>	
 				<!-- Ticket 78428 New USB Classes Must wait -->
 				<!--
@@ -2063,6 +2077,20 @@
 					<Semaphore>USB_DEVICE_MSC</Semaphore>
 					<Semaphore>MSC_FS</Semaphore>
 				</Mode>	
+				<Mode Name="CCID_FS" UserName="Smart Card Class (CCID)">
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_CCID_FS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_FULL_SPEED</Semaphore>
+					<Semaphore>CCID_FS</Semaphore>
+				</Mode>
+				<Mode Name="MTP_FS" UserName="Media Transfer Protocol (MTP)">				
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_MTP_FS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_FULL_SPEED</Semaphore>
+					<Semaphore>MTP_FS</Semaphore>
+				</Mode>
 				<!-- Ticket 78428 New USB Classes : Must wait -->
 				<!-- 
 				<Mode Name="BILLBOARD_FS" UserName="Bill Board Class" RemoveCondition="!(DIE419 | DIE421 | DIE434 | DIE413 | DIE423 | DIE463 | DIE441 | DIE431)">
diff --git a/mcu/IP/USB_DEVICE-v2.0_Cube_Modes.xml b/mcu/IP/USB_DEVICE-v2.0_Cube_Modes.xml
index ccce27a..76f5c9f 100644
--- a/mcu/IP/USB_DEVICE-v2.0_Cube_Modes.xml
+++ b/mcu/IP/USB_DEVICE-v2.0_Cube_Modes.xml
@@ -1433,14 +1433,21 @@
 					<Semaphore>USB_DEVICE_MSC</Semaphore>
 					<Semaphore>MSC_FS</Semaphore>
 				</Mode>
-				<!--<Mode Name="MTP_FS" UserName="MTP_FS">				
+				<Mode Name="CCID_FS" UserName="Smart Card Class (CCID)">
+					<SignalLogicalOp Name="AND">
+						<Signal IOMode="" Name="VS_USB_DEVICE_CCID_FS"/>
+					</SignalLogicalOp>
+					<Semaphore>DEVICE_FULL_SPEED</Semaphore>
+					<Semaphore>CCID_FS</Semaphore>
+				</Mode>
+				<Mode Name="MTP_FS" UserName="Media Transfer Protocol (MTP)">				
 					<SignalLogicalOp Name="AND">
 						<Signal IOMode="" Name="VS_USB_DEVICE_MTP_FS"/>
 					</SignalLogicalOp>
 					<Semaphore>DEVICE_FULL_SPEED</Semaphore>
 					<Semaphore>MTP_FS</Semaphore>
 				</Mode>	
-				-->
+				
 			</ModeLogicOperator>	
 			<Semaphore>USB_DEVICE_FS_CLASSES</Semaphore>
 			<!--<Condition Expression="(MW_USB_OTG_FS_MW_DEVICE | MW_USB_MW_DEVICE)&amp; (!USB_DEVICE_HS_CLASSES)" Diagnostic="Active only when USB_OTG_FS IP is configured in Device mode"/>-->
diff --git a/mcu/packs/STMicroelectronics.USB_DEVICE.1.0.0.vpdsc b/mcu/packs/STMicroelectronics.USB_DEVICE.1.0.0.vpdsc
index fb39bed..b1ab4ab 100644
--- a/mcu/packs/STMicroelectronics.USB_DEVICE.1.0.0.vpdsc
+++ b/mcu/packs/STMicroelectronics.USB_DEVICE.1.0.0.vpdsc
@@ -101,6 +101,18 @@
         <file category="other" name="dummy"/><!-- required for XSD validation -->
       </files>
     </component>
+    <component Cclass="USB" Cgroup="USB Device" Csub="CCID FS" Cversion="3.0">
+      <description>[Modes:CCID_FS]</description>
+      <files>
+        <file category="other" name="dummy"/><!-- required for XSD validation -->
+      </files>
+    </component>
+    <component Cclass="USB" Cgroup="USB Device" Csub="MTP FS" Cversion="3.0">
+      <description>[Modes:MTP_FS]</description>
+      <files>
+        <file category="other" name="dummy"/><!-- required for XSD validation -->
+      </files>
+    </component>
   </components>
 
 </package>
diff --git a/mcu/packs/STMicroelectronics.USB_DEVICE.2.0.0.vpdsc b/mcu/packs/STMicroelectronics.USB_DEVICE.2.0.0.vpdsc
index 0a7ec7f..4977422 100644
--- a/mcu/packs/STMicroelectronics.USB_DEVICE.2.0.0.vpdsc
+++ b/mcu/packs/STMicroelectronics.USB_DEVICE.2.0.0.vpdsc
@@ -48,6 +48,18 @@
         <file category="other" name="dummy"/><!-- required for XSD validation -->
       </files>
     </component>
+    <component Cclass="USB" Cgroup="USB Device" Csub="CCID FS" Cversion="3.0">
+      <description>[Modes:CCID_FS]</description>
+      <files>
+        <file category="other" name="dummy"/><!-- required for XSD validation -->
+      </files>
+    </component>
+    <component Cclass="USB" Cgroup="USB Device" Csub="MTP FS" Cversion="3.0">
+      <description>[Modes:MTP_FS]</description>
+      <files>
+        <file category="other" name="dummy"/><!-- required for XSD validation -->
+      </files>
+    </component>
   </components>
 
 </package>
diff --git a/mcu/packs/STMicroelectronics.USB_DEVICE.3.0.0.vpdsc b/mcu/packs/STMicroelectronics.USB_DEVICE.3.0.0.vpdsc
index b90f27f..e8fef4d 100644
--- a/mcu/packs/STMicroelectronics.USB_DEVICE.3.0.0.vpdsc
+++ b/mcu/packs/STMicroelectronics.USB_DEVICE.3.0.0.vpdsc
@@ -48,6 +48,18 @@
         <file category="other" name="dummy"/><!-- required for XSD validation -->
       </files>
     </component>
+    <component Cclass="USB" Cgroup="USB Device" Csub="CCID FS" Cversion="3.0">
+      <description>[Modes:CCID_FS]</description>
+      <files>
+        <file category="other" name="dummy"/><!-- required for XSD validation -->
+      </files>
+    </component>
+    <component Cclass="USB" Cgroup="USB Device" Csub="MTP FS" Cversion="3.0">
+      <description>[Modes:MTP_FS]</description>
+      <files>
+        <file category="other" name="dummy"/><!-- required for XSD validation -->
+      </files>
+    </component>
   </components>
 
 </package>
-- 
2.39.2

Исправляем в базе данных устройств конкретно для семейства F4 (для других семейств, возможно, потребуются другие правки) набор добавляемых файлов исходных кодов (sources и headers) в проект:

Скрытый текст
Date: Tue, 27 Aug 2024 22:11:36 +0300
Subject: [PATCH] Fix CCID & MTP files for F4

---
 mcu/config/USB_DEVICE-STM32F4xx_Configs.xml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/mcu/config/USB_DEVICE-STM32F4xx_Configs.xml b/mcu/config/USB_DEVICE-STM32F4xx_Configs.xml
index 66666d3..deaa6f5 100644
--- a/mcu/config/USB_DEVICE-STM32F4xx_Configs.xml
+++ b/mcu/config/USB_DEVICE-STM32F4xx_Configs.xml
@@ -551,6 +551,10 @@
         <SubComponent Csub="CCID" Description="Ccid">
             <File Category="header" Name="Class/CCID/Inc/usbd_ccid.h"/>
             <File Category="source" Name="Class/CCID/Src/usbd_ccid.c"/>
+            <File Category="source" Name="Class/CCID/Src/usbd_ccid_cmd.c"/>
+            <File Category="source" Name="Class/CCID/Src/usbd_ccid_if_template.c"/>
+            <File Category="source" Name="Class/CCID/Src/usbd_ccid_smartcard_template.c"/>
+            <File Category="source" Name="Class/CCID/Src/usbd_ccid_sc_if_template.c"/>
         </SubComponent>
         <SubComponent Csub="CDC" Description="CDC">
             <File Category="header" Name="Class/CDC/Inc/usbd_cdc.h"/>
@@ -581,6 +585,8 @@
         <SubComponent Csub="MTP" Description="Media Transport Protocol">
             <File Category="header" Name="Class/MTP/Inc/usbd_mtp.h"/>
             <File Category="source" Name="Class/MTP/Src/usbd_mtp.c"/>
+            <File Category="source" Name="Class/MTP/Src/usbd_mtp_storage.c"/>
+            <File Category="source" Name="Class/MTP/Src/usbd_mtp_opt.c"/>
         </SubComponent>
         <SubComponent Csub="BILLBOARD" Description="Bill Board">
             <File Category="header" Name="Class/BillBoard/Inc/usbd_billboard.h"/>
-- 
2.39.2

Исправляем ошибки в HAL библиотеках для F4:

Скрытый текст
Date: Tue, 27 Aug 2024 22:09:42 +0300
Subject: [PATCH] Fix CCID

---
 .../Class/CCID/Src/usbd_ccid_if_template.c                | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Middlewares/ST/STM32_USB_Device_Library/Class/CCID/Src/usbd_ccid_if_template.c b/Middlewares/ST/STM32_USB_Device_Library/Class/CCID/Src/usbd_ccid_if_template.c
index 10fb344d..e51fd9b5 100644
--- a/Middlewares/ST/STM32_USB_Device_Library/Class/CCID/Src/usbd_ccid_if_template.c
+++ b/Middlewares/ST/STM32_USB_Device_Library/Class/CCID/Src/usbd_ccid_if_template.c
@@ -35,6 +35,8 @@ static uint8_t CCID_Send_Process(uint8_t *Command, uint8_t *Data);
 static uint8_t CCID_Response_Process(void);
 static uint8_t CCID_SetSlotStatus(USBD_HandleTypeDef *pdev);
 
+extern USBD_HandleTypeDef hUsbDeviceFS;
+
 /* Private functions ---------------------------------------------------------*/
 
 /**
@@ -102,9 +104,9 @@ uint8_t CCID_DeInit(USBD_HandleTypeDef  *pdev)
 static uint8_t CCID_ControlReq(uint8_t req, uint8_t *pbuf, uint16_t *length)
 {
 #ifdef USE_USBD_COMPOSITE
-  USBD_CCID_HandleTypeDef  *hccid = (USBD_CCID_HandleTypeDef *)USBD_Device.pClassDataCmsit[USBD_Device.classId];
+  USBD_CCID_HandleTypeDef  *hccid = (USBD_CCID_HandleTypeDef *)hUsbDeviceFS.pClassDataCmsit[hUsbDeviceFS.classId];
 #else
-  USBD_CCID_HandleTypeDef  *hccid = (USBD_CCID_HandleTypeDef *)USBD_Device.pClassData;
+  USBD_CCID_HandleTypeDef  *hccid = (USBD_CCID_HandleTypeDef *)hUsbDeviceFS.pClassData;
 #endif /* USE_USBD_COMPOSITE */
 
   UNUSED(length);
@@ -117,7 +119,7 @@ static uint8_t CCID_ControlReq(uint8_t req, uint8_t *pbuf, uint16_t *length)
       hccid->slot_nb = ((uint16_t) * pbuf & 0x0fU);
       hccid->seq_nb = (((uint16_t) * pbuf & 0xf0U) >> 8);
 
-      if (CCID_CmdAbort(&USBD_Device, (uint8_t)hccid->slot_nb, (uint8_t)hccid->seq_nb) != 0U)
+      if (CCID_CmdAbort(&hUsbDeviceFS, (uint8_t)hccid->slot_nb, (uint8_t)hccid->seq_nb) != 0U)
       {
         /* If error is returned by lower layer :
         Generally Slot# may not have matched */
-- 
2.39.2

Результат

После всех исправлений, при создании проекта появляются 2 новых USB класса:

После сборки проекта устройства распознаются следующим образом:

MTP:

Скрытый текст
Bus 007 Device 005: ID 0483:5770 STMicroelectronics STM32 Mtp Class
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0483 STMicroelectronics
  idProduct          0x5770 
  bcdDevice            2.00
  iManufacturer           1 STMicroelectronics
  iProduct                2 STM32 Mtp Class
  iSerial                 3 378C376F3436
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0027
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass         6 Imaging
      bInterfaceSubClass      1 Still Image Capture
      bInterfaceProtocol      1 Picture Transfer Protocol (PIMA 15470)
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              16

Windows:

CCID:

Скрытый текст
Bus 007 Device 007: ID 0483:2105 STMicroelectronics STM32 Ccid Class
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0483 STMicroelectronics
  idProduct          0x2105 
  bcdDevice            2.00
  iManufacturer           1 STMicroelectronics
  iProduct                2 STM32 Ccid Class
  iSerial                 3 378C376F3436
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x005d
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass        11 Chip/SmartCard
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      ChipCard Interface Descriptor:
        bLength                54
        bDescriptorType        33
        bcdCCID              1.10  (Warning: Only accurate for version 1.0)
        nMaxSlotIndex           0
        bVoltageSupport         7  5.0V 3.0V 1.8V 
        dwProtocols             3  T=0 T=1
        dwDefaultClock       3600
        dwMaxiumumClock      3600
        bNumClockSupported      0
        dwDataRate           9677 bps
        dwMaxDataRate        9677 bps
        bNumDataRatesSupp.     53
        dwMaxIFSD             254
        dwSyncProtocols  00000000 
        dwMechanical     00000000 
        dwFeatures       000104BA
          Auto configuration based on ATR
          Auto voltage selection
          Auto clock change
          Auto baud rate change
          Auto PPS made by CCID
          Auto IFSD exchange
          TPDU level exchange
        dwMaxCCIDMsgLen       271
        bClassGetResponse      00
        bClassEnvelope         00
        wlcdLayout           none
        bPINSupport             3  verification modification
        bMaxCCIDBusySlots       1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              16
Device Status:     0x0001
  Self Powered

Windows:

Комментарии (0)