How do I get two VCPs with only one USB connector? - stm32

I've tried to emulate two virtual COM ports with only one USB connector (CN5 in the STM32F4 Discovery Board), but in vain.
I know that I have to configure the composite CDC class to have multiple interfaces using an ACM functional descriptor (abstract control model) for virtual COM ports communications, but how do I make them two VCPs?
I've done one CCI (communications class interface) and one DCI (data class interface), and that allowed me to have only one VCP in Device Manager.
I've tried to do two CCIs and two DCIs, but it didn't work!
This is my device descriptor for interface association descriptors:
/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
#if (USBD_LPM_ENABLED == 1)
0x01, /* bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /* bcdUSB */
#endif
0x02,
0xEF, /* bDeviceClass */
0x02, /* bDeviceSubClass */
0x01, /* bDeviceProtocol */
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
LOBYTE(USBD_VID), /* idVendor */
HIBYTE(USBD_VID), /* idVendor */
LOBYTE(USBD_PID_HS), /* idVendor */
HIBYTE(USBD_PID_HS), /* idVendor */
0x00, /* bcdDevice rel. 2.00 */
0x02,
USBD_IDX_MFC_STR, /* Index of manufacturer string */
USBD_IDX_PRODUCT_STR, /* Index of product string */
USBD_IDX_SERIAL_STR, /* Index of serial number string */
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
} ;
And my CDC configuration with two IADs one CCI and one DCI each:
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x04, /* bNumInterfaces: 4 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: self powered */
0x32, /* MaxPower 0 mA */
/*---------------------------------------------------------------------------*/
// IAD0
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x00, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
/*Interface0 Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
0x10, /* bInterval: */
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*---------------------------------------------------------------------------*/
// IAD1
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x02, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
/*Interface1 Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x02, /* bMasterInterface: Communication class interface */
0x03, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP4, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
0x10, /* bInterval: */
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x03, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP3, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP3, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00 /* bInterval: ignore for Bulk transfer */
} ;
How do I configure the CDC Class to have two VCPs? What's wrong with these configurations?

There is an error in the second Call Management Functional Descriptor - the bDataInterface is set to 1 (the first Call Management Functional Descriptor also set to use Interface 1 as the data interface). The correct values are 1 for the first descriptor and 3 for the second one.

Related

stm32 cdc+audio USB Composite Device

I am currently implementing the composite device of stm32 audio cdc, but the display of cdc in the windows device is normal, and the audio is an exclamation mark. May I ask where there may be problems?
I tried to adjust the interface of cdc and audio, but it will be successful. I want to know how to change it if the cdc is placed in front.
Below is my descriptor
__ALIGN_BEGIN static uint8_t USBD_AUDIO_CDC_CfgDesc[USB_AUDIO_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
LOBYTE(USB_AUDIO_CDC_CONFIG_DESC_SIZ), /* wTotalLength: Bytes returned */
HIBYTE(USB_AUDIO_CDC_CONFIG_DESC_SIZ),
0x04, /*bNumInterfaces: 4 interfaces (2 for AUDIO, 2 for CDC)*/
0x01, /*bConfigurationValue: Configuration value*/
0x00, /*iConfiguration: Index of string descriptor describing the configuration*/
0x80, /*bmAttributes: bus powered */
0xFA, /*MaxPower 100 mA: this current is used for detecting Vbus*/
/*9*/
/******** /IAD should be positioned just before the CDC interfaces ******
IAD to associate the two CDC interfaces */
0x08, /* bLength */
0x0B, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass */
0x02, /* bFunctionSubClass */
0x01, /* bFunctionProtocol */
0x02, /* iFunction (Index of string descriptor describing this function) */
/*49(117)*/
/************************ CDC interface ********************************/
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
CDC_INTERFACE0, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*58 (126)*/
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*63 (131)*/
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*68 (136)*/
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*72 (140)*/
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*77 (145)*/
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
0x10, /* bInterval: */
/*84 (152)*/
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
CDC_INTERFACE1, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*93 (161)*/
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*100 (168)*/
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*107(175)*/
/*** Interface Association Descriptor: Audio Function 1******/
0x08, /* bLength */
0x0B, /* bDescriptorType */
0x02, /* bFirstInterface *///interafe 2 to 3
0x02, /* bInterfaceCount */
0x01, /* bFunctionClass */
0x00, /* bFunctionSubClass */
0x00, /* bFunctionProtocol */
0x00, /* iFunction (Index of string descriptor describing this function) */
/*8 (17)*/
/* USB Speaker Standard interface descriptor */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
AUDIO_INTERFACE0, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte (26)*/
/* USB Speaker Class-specific AC Interface Descriptor */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */
0x00, /* 1.00 */ /* bcdADC */
0x01,
0x1E, /* wTotalLength = 39 +1 channel -9*/
0x00,
0x01, /* bInCollection */
0x01, /* baInterfaceNr */
/* 09 byte (35)*/
/* USB Speaker Input Terminal Descriptor */
AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */
0x01, /* bTerminalID */
0x01, /* wTerminalType AUDIO_TERMINAL_USB_STREAMING 0x0101 */
0x02, //0x01 -> 0x02
0x00, /* bAssocTerminal */
0x02, /* bNrChannels */ //0x01->0x02
0x03, /* wChannelConfig 0x0000 Mono */
0x00,
0x00, /* iChannelNames */
0x00, /* iTerminal */
/* 12 byte (47)*/
/* USB Speaker Audio Feature Unit Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */ //AUDIO_CONTROL_FEATURE_UNIT(0x06) -> AUDIO_CONTROL_OUTPUT_TERMINAL(0x03)
AUDIO_OUT_STREAMING_CTRL, /* bUnitID */
0x01, /* bSourceID */
0x01, /* bControlSize */
0x00, //AUDIO_CONTROL_MUTE, /* bmaControls(0) */
0x01, //0 ->1 /* bmaControls(1) */
//0x01,
0x00, /* iTerminal */
/* 09 +1 byte (57)*/
/*USB Speaker Output Terminal Descriptor */
// 0x09, /* bLength */
// AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ //AUDIO_INTERFACE_DESCRIPTOR_TYPE ->0x04
// AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */ //AUDIO_CONTROL_OUTPUT_TERMINAL -> 0x01
// 0x03, /* bTerminalID */ //0x03->0x00
// 0x01, /* wTerminalType 0x0301->0x0100*/ //0x01->0x00
// 0x03, //0x03 ->0x01
// 0x00, /* bAssocTerminal */ //0x00->0x02
// 0x02, /* bSourceID */ //0x02-> 0x00
// 0x00, /* iTerminal */
/* 09 byte (66)*/
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwith */
/* Interface 1, Alternate Setting 0 */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
AUDIO_INTERFACE1, /* bInterfaceNumber */
0x00, /* bAlternateSetting *///0x00->0x01
0x00, /* bNumEndpoints *///0x00->0x01
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte*/
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Operational */
/* Interface 1, Alternate Setting 1 */
AUDIO_INTERFACE_DESC_SIZE, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
AUDIO_INTERFACE1, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* 09 byte (75)*/
/* USB Speaker Audio Streaming Interface Descriptor */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x02, /* bTerminalLink */ //0x01->0x02
0x01, /* bDelay */
0x01, /* wFormatTag AUDIO_FORMAT_PCM 0x0001 */
0x00,
/* 07 byte (82)*/
/* USB Speaker Audio Type III Format Interface Descriptor */
0x0B, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_I, /* bFormatType */
0x01, /* bNrChannels */ //0x02->0x01
0x02, /* bSubFrameSize : 2 Bytes per frame (16bits) */
16, /* bBitResolution (16-bits per sample) */
0x01, /* bSamFreqType only one frequency supported */
AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ), /* Audio sampling frequency coded on 3 bytes */
/* 11 byte (93)*/
/* Endpoint 1 - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType */
AUDIO_IN_EP, /* bEndpointAddress 1 out endpoint */ //AUDIO_OUT_EP->0x81
USBD_EP_TYPE_ISOC, /* bmAttributes */
AUDIO_PACKET_SZE(USBD_AUDIO_FREQ), /* wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */
AUDIO_FS_BINTERVAL, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* 09 byte (102)*/
/* Endpoint - Audio Streaming Descriptor*/
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x80, /* bmAttributes *///0x00->0x80
0x00, /* bLockDelayUnits */
0x00, /* wLockDelay */
0x00,
/* 07 byte (109)*/
} ;

How to access from Twig to the underlying object in an embedded form in a Symfony project

In a medical record project developed with Symfony 2.7.7 I have to track the outcome of supplementary medical examinations. These can have many typology of outcomes according to the type of exam done. In particular, the parameters to take into consideration can be the following:
normal/altered;
positive/negative;
value.
For this reason I have done an entity SupplementaryMedicalExamination in this way:
class SupplementaryMedicalExamination extends MedicalExamination
{
/**
* #var string $examination
*
* #ORM\Column(type="string", length=255, nullable=false)
*
*/
private $examination;
/**
* #var bool $hasNormalOrAlteredEvaluation;
*
* #ORM\Column(name="has_normal_or_altered_evaluation", type="boolean", nullable=false)
*
*/
private $hasNormalOrAlteredEvaluation;
/**
* #var bool $hasNegativeOrPositiveEvaluation
*
* #ORM\Column(name="has_negative_or_positive_evaluation", type="boolean", nullable=false)
*
*/
private $hasNegativeOrPositiveEvaluation;
/**
* #var bool $hasValue
*
* #ORM\Column(name="has_value", type="boolean", nullable=false)
*
*/
private $hasValue;
}
A MedicalRecord entity has a one to many relationship with supplementary examinations.
/**
* AppBundle\Entity\HealthData\MedicalRecord
*
* #ORM\Table(name="medical_record")
* #ORM\Entity(repositoryClass="MedicalRecordRepository")
* #ORM\HasLifecycleCallbacks
*/
class MedicalRecord
{
//other stuff
/**
* #var ArrayCollection $supplementaryExaminations
*
* #ORM\OneToMany(targetEntity="\AppBundle\Entity\HealthData\MedicalRecordSupplementaryExamination", mappedBy = "medicalRecord")
*/
protected $supplementaryExaminations;
//other stuff
}
And the MedicalRecordSupplementaryExamination should contain the outcomes of each supplementary examination.
/**
* AppBundle\Entity\HealthData\MedicalRecordSupplementaryExamination
*
* #ORM\Table(name="medical_record_supplementary_examination")
* #ORM\Entity()
* #ORM\HasLifecycleCallbacks
*
*/
class MedicalRecordSupplementaryExamination
{
/**
* #var int $id
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* #var bool $isAltered
*
* #ORM\Column(name="is_altered", type="boolean")
*/
protected $isAltered;
/**
* #var bool $isPositive
*
* #ORM\Column(name="is_positive", type="boolean")
*/
protected $isPositive;
/**
* #var string $alterations
*
* #ORM\Column(type="string", length=255)
*/
protected $alterations;
/**
* #var float $value
*
* #ORM\Column(type = "decimal", precision = 10, scale = 2)
*/
protected $value;
/**
* #var MedicalRecord $medicalRecord
*
* #ORM\ManyToOne(targetEntity="medicalRecord", inversedBy = "supplementaryExaminations")
* #ORM\JoinColumn(name="medical_record_id", referencedColumnName="id")
*/
protected $medicalRecord;
/**
* #var SupplementaryMedicalExamination $supplementaryExamination
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\HealthData\Core\SupplementaryMedicalExamination")
* #ORM\JoinColumn(name="supplementary_examination_id", referencedColumnName="id")
*/
protected $supplementaryExamination;
}
In the MedicalRecordType, I include the MedicalRecordExamination as a collection and in the MedicalRecordController I add in the MedicalRecord object many instance of MedicalRecordSupplementaryExamination according to the SupplementaryExamination available.
The problem is that I would like to show in the template the right form fields according to the type of outcome of the MedicalSupplementaryExamination.
I would like to do something like this but I don't know how because at this level I'm working with a FormView instance and I can't access the underlying object:
{% for supplementaryExamination in form.supplementaryExaminations %}
{% if supplementaryExamination.hasNormalOrAlteredEvaluation == true %}
{{ form_row(supplementaryExamination.isAltered) }}
{% endif %}
{% endfor %}
I have seen this post: How to access an underlying object from a Twig's FormView in a template? but I can't understand how to apply this solution to my case.
Thank you
Referring from the doc on how rendering form in the twig template:
You can access the current data of your form via form.vars.value:
So, in your case, you can try this:
{% if supplementaryExamination.vars.value.supplementaryExamination.hasNormalOrAltered‌​Evaluation == true %}
instead of this:
{% if supplementaryExamination.hasNormalOrAlteredEvaluation == true %}
Hope this help

ManyToMany odm symfony2

I need to do this schema in symfony2 with odm, I have problems because the relasion is ManyToMany and I dont know How to do this. I need help.
I have the entity "Persona" and entity "Direccion" and these generate the entity "Persona-has-Direccion" with his ids and the attribute "viveAqui".
Persona{
_id: 1000,
nombre: 'Carlos',
apellidos: 'Gracia',
genero: 'M',
direcciones: [{
direccion_id: 1,
viveAqui: true
}.{
direccion_id: 2,
viveAqui: true
}]
}
My code:
/**
* #MongoDB\Document
*/
class Direccion
{
/**
* #MongoDB\Id(strategy="auto")
*/
private $id;
/**
* #MongoDB\String
*/
private $pais;
/**
* #MongoDB\String
*/
private $estado;
/**
* #MongoDB\String
*/
private $ciudad;
/**
* #MongoDB\Boolean
*/
private $viveAqui;
}
/**
* #MongoDB\Document
*/
class Persona
{
/**
* #MongoDB\Id(strategy="auto")
*/
private $id;
/**
* #MongoDB\String
*/
private $nombre;
/**
* #MongoDB\String
*/
private $apellidos;
/**
* #MongoDB\String
*/
private $genero;
}
Not sure what this mean:
these generate the entity "Persona-has-Direccion"
but I think basically simple reference is what you need:
class Persona
{
/**
*
* #MongoDB\ReferenceMany(targetDocument="Direccion", simple=true)
*/
protected $direcciones;
Then generate setter and getter (adder and remover in this case):
php app/console doctrine:mongodb:generate:documents YourBundle
You can save it later:
$persona = new Persona();
$direccion = new Direccion();
$persona->addDireccion($direccion);
$dm->persist($persona);
$dm->flush($persona);
Ok, I have a solution, but I dont know if it is correct.
My code:
/**
* #MongoDB\Document
*/
class Persona
{
/**
* #MongoDB\Id(strategy="auto")
*/
private $id;
/**
* #MongoDB\EmbedMany(targetDocument="PersonaDireccion")
*/
private $direccionPersona;
/**
* #MongoDB\String
*/
private $nombre;
/**
* #MongoDB\String
*/
private $apellidos;
/**
* #MongoDB\String
*/
private $genero;
}
class PersonaDireccion
{
/**
* #MongoDB\Id(strategy="auto")
*/
private $id;
/**
* #MongoDB\ReferenceOne(targetDocument="Direccion", cascade={"persist", "remove"})
*/
private $direccion;
/**
* #MongoDB\Boolean
*/
private $viveAqui;
}
/**
* #MongoDB\Document
*/
class Direccion
{
/**
* #MongoDB\Id(strategy="auto")
*/
private $id;
/**
* #MongoDB\String
*/
private $pais;
/**
* #MongoDB\String
*/
private $estado;
/**
* #MongoDB\String
*/
private $ciudad;
}
Now I have 3 documents. The document "PersonaDireccion" has referenceOne to "Direccion". The document "Persona" has embedMany "PersonaDireccion". The schema is the next:
Persona{
_id: 1000,
nombre: 'Carlos',
apellidos: 'Gracia',
genero: 'M',
direcciones: [{
direccionPersona_id: 1,
direccion_id: 1,
viveAqui: true
}.{
direccionPersona_id: 2,
direccion_id: 2,
viveAqui: true
}]
}

How to make multiply select box from entity in a form in Symfony 2

I'm working on a form in Symfony 2. The form is for my projects and each of my project can be an artistic, technic or both categorie of project. At first, I tried doing a select, butt it only allow me to choose one of those two categories.
Than I tough that I could generate a select box for each categories in my entity. That way, I could choose as much categories I want.
-Now, how do I do that?
-I would like that the checkbox be selected when I pass a project to the form (if the project is techic project, the technic checkbox is selected)... I don't now if the form would take care of that by itself.
Here is my form:
<?php
namespace AdminBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
Class ProjetType extends AbstractType
{
public function buildForm(FormBuilderInterface $constructeur, array $options)
{
$constructeur
->add('image', 'text')
->add('technologie', 'text')
->add('annee', 'text', array('label'=>'année'))
->add('type', 'entity', [
'class'=>'PublicBundle\Entity\Type',
'property'=>'nom',
'required'=>true,
])
->add('fichier', 'text')
->add('largeur', 'text')
->add('hauteur', 'text')
//What I had before
/*->add('categories', 'entity', [
'label'=>'catégorie',
'class'=>'PublicBundle\Entity\Categorie',
'property'=>'tag',
'required'=>true,
])*/
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AdminBundle\Entity\Projet',
));
}
public function getName()
{
return 'projet';
}
}
My project entity:
<?php
namespace PublicBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Projet
*
* #ORM\Table(name="pt_projet");
* #ORM\Entity
* #ORM\Entity(repositoryClass="PublicBundle\Entity\ProjetDepot")
*/
class Projet
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
//ID du projet
protected $id;
/**
* #ORM\OneToMany(targetEntity="ProjetInt", mappedBy="projet", orphanRemoval=true)
*/
protected $descriptions;
/**
* #ORM\Column(name="pro_img", type="string", length=64, unique=true)
*/
//Nom du fichier de l'image du projet
protected $image;
/**
* #ORM\Column(name="pro_technologie_utilisee", type="text", length=200)
*/
//Text qui liste tout les technologies utilisées pour le projet
protected $technologie;
/**
* #ORM\Column(name="pro_annee", type="integer", length=4)
*/
//Année de réalisation du projet
protected $annee;
/**
* #ORM\ManyToOne(targetEntity="Type", inversedBy="projets")
* #ORM\JoinColumn(name="pro_type", referencedColumnName="id", nullable=false)
*/
//Clef étrangère du type de projet
//Le type de projet ne correspond pas à la catégore. Il peu être Unity, flash, image, vidéo, etc. Il permet de savoir quelle page charger pour pouvoir intégrer le projet dans le portfolio.
protected $type;
/**
* #ORM\Column(name="pro_fichier", type="string", length=64, unique=true)
*/
//Nom du fichier du projet
private $fichier;
/**
* #ORM\Column(name="pro_largeur", type="integer")
*/
//Largeur du projet
protected $largeur;
/**
* #ORM\Column(name="pro_hauteur", type="integer")
*/
//Hauteur du projet
protected $hauteur;
/**
* #ORM\ManyToMany(targetEntity="Categorie", cascade={"persist"})
*/
//La ou les catégories du projet
private $categories;
/**
* Constructor
*/
public function __construct()
{
$this->descriptions=new ArrayCollection();
$this->categories=new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set image
*
* #param string $image
* #return Projet
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set technologie
*
* #param string $technologie
* #return Projet
*/
public function setTechnologie($technologie)
{
$this->technologie = $technologie;
return $this;
}
/**
* Get technologie
*
* #return string
*/
public function getTechnologie()
{
return $this->technologie;
}
/**
* Set annee
*
* #param integer $annee
* #return Projet
*/
public function setAnnee($annee)
{
$this->annee = $annee;
return $this;
}
/**
* Get annee
*
* #return integer
*/
public function getAnnee()
{
return $this->annee;
}
/**
* Set fichier
*
* #param string $fichier
* #return Projet
*/
public function setFichier($fichier)
{
$this->fichier = $fichier;
return $this;
}
/**
* Get fichier
*
* #return string
*/
public function getFichier()
{
return $this->fichier;
}
/**
* Set largeur
*
* #param integer $largeur
* #return Projet
*/
public function setLargeur($largeur)
{
$this->largeur = $largeur;
return $this;
}
/**
* Get largeur
*
* #return integer
*/
public function getLargeur()
{
return $this->largeur;
}
/**
* Set hauteur
*
* #param integer $hauteur
* #return Projet
*/
public function setHauteur($hauteur)
{
$this->hauteur = $hauteur;
return $this;
}
/**
* Get hauteur
*
* #return integer
*/
public function getHauteur()
{
return $this->hauteur;
}
/**
* Add descriptions
*
* #param \PublicBundle\Entity\ProjetInt $descriptions
* #return Projet
*/
public function addDescription(\PublicBundle\Entity\ProjetInt $descriptions)
{
$this->descriptions[] = $descriptions;
return $this;
}
/**
* Remove descriptions
*
* #param \PublicBundle\Entity\ProjetInt $descriptions
*/
public function removeDescription(\PublicBundle\Entity\ProjetInt $descriptions)
{
$this->descriptions->removeElement($descriptions);
}
/**
* Get descriptions
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getDescriptions()
{
return $this->descriptions;
}
/**
* Set type
*
* #param \PublicBundle\Entity\Type $type
* #return Projet
*/
public function setType(\PublicBundle\Entity\Type $type)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* #return \PublicBundle\Entity\Type
*/
public function getType()
{
return $this->type;
}
/**
* Add categories
*
* #param \PublicBundle\Entity\Categorie $categories
* #return Projet
*/
public function addCategory(\PublicBundle\Entity\Categorie $categories)
{
$this->categories[] = $categories;
return $this;
}
/**
* Remove categories
*
* #param \PublicBundle\Entity\Categorie $categories
*/
public function removeCategory(\PublicBundle\Entity\Categorie $categories)
{
$this->categories->removeElement($categories);
}
/**
* Get categories
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCategories()
{
return $this->categories;
}
}
Category entity:
<?php
namespace PublicBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Catégorie
*
* #ORM\Table(name="pt_categorie");
* #ORM\Entity
* #ORM\Entity(repositoryClass="PublicBundle\Entity\CategorieDepot")
*/
class Categorie
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
//ID de la catégorie
protected $id;
/**
* #ORM\Column(name="cat_tag", type="string",length=255, unique=true)
*/
//Tag de la catégorie
protected $tag;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set tag
*
* #param string $tag
* #return Categorie
*/
public function setTag($tag)
{
$this->tag = $tag;
return $this;
}
/**
* Get tag
*
* #return string
*/
public function getTag()
{
return $this->tag;
}
}
Use multiple and expanded options of entity field type:
->add('categories', 'entity', [
'label'=>'catégorie',
'class'=>'PublicBundle\Entity\Categorie',
'property'=>'tag',
'required'=>true,
'multiple'=>true,
'expanded'=>true,
])
Documentation on topic: http://symfony.com/doc/current/reference/forms/types/choice.html#select-tag-checkboxes-or-radio-buttons

FOSUserBundle using ORM and FOSMessageBundle using MongoDB

I need implement FOSUserBundle using ORM database and FOSMessageBundle using MongoDB (ODM database). Is it posible?
I configure FOSUserBundle using ORM and works.
I am triying to configure FOSMessageBundle using the documentation https://github.com/FriendsOfSymfony/FOSMessageBundle/blob/master/Resources/doc/01b-odm-models.md the problem it is here:
/**
* #MongoDB\ReferenceOne(targetDocument="Acme\UserBundle\Document\User")
*/
protected $sender;
I don´t have Acme\UserBundle\Document\User, I have Acme\UserBundle\Entity\User .
If I put Acme\UserBundle\Entity\User don´t work.
I try to use http://doctrine-mongodb-odm.readthedocs.org/en/latest/cookbook/blending-orm-and-mongodb-odm.html but I need help.
Another option it is create a duplicate User table in MongoDB but I don't know how I can do this.
Thanks for your solution Nawdal Serrar.
I read the documentation and try this. Don`t work, can you help me please?
Message.php
/**
* #MongoDB\Document
*/
class Message extends BaseMessage{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\EmbedMany(targetDocument="xxx\MensajeriaBundle\Document\MessageMetadata")
*/
protected $metadata;
/**
* #MongoDB\ReferenceOne(targetDocument="xxx\MensajeriaBundle\Document\Thread")
*/
protected $thread;
/**
* #Gedmo\ReferenceMany(type="entity", class="xxx\WebBundle\Entity\usuarios", mappedBy="senderMongo")
*/
protected $sender;
public function __construct()
{
$this->metadata = new \Doctrine\Common\Collections\ArrayCollection();
$this->createdAt = new \DateTime();
}
}
MessageMetadata.php
/**
* #ODM\EmbeddedDocument
*/
class MessageMetadata extends BaseMessageMetadata
{
/**
* #Gedmo\ReferenceMany(type="entity", class="xxx\WebBundle\Entity\usuarios", mappedBy="participantMesssageMongo")
*/
protected $participant;
}
Thread.class
/**
* #MongoDB\Document
*/
class Thread extends BaseThread
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\ReferenceMany(targetDocument="xxx\MensajeriaBundle\Document\Message")
*/
protected $messages;
/**
* #MongoDB\EmbedMany(targetDocument="xxx\MensajeriaBundle\Document\ThreadMetadata")
*/
protected $metadata;
/**
* #Gedmo\ReferenceMany(type="entity", class="xxx\WebBundle\Entity\usuarios", mappedBy="participantsMongo")
*/
protected $participants;
/**
* #Gedmo\ReferenceMany(type="entity", class="xxx\WebBundle\Entity\usuarios", mappedBy="createdByMongo")
*/
protected $createdBy;
}
ThreadMetadata.php
/**
* #ODM\EmbeddedDocument
*/
class ThreadMetadata extends BaseThreadMetadata
{
/**
* #Gedmo\ReferenceMany(type="entity", class="xxx\WebBundle\Entity\usuarios", mappedBy="participantThreatMongo")
*/
protected $participant;
}
usuarios.php
/**
* #Gedmo\ReferenceOne(type="document", class="xxx\MensajeriaBundle\Document\Message", inversedBy="sender", identifier="senderId")
*/
private $senderMongo;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $senderId;
/**
* #Gedmo\ReferenceOne(type="document", class="xxx\MensajeriaBundle\Document\MessageMetadata", inversedBy="participant", identifier="participantMessageId")
*/
private $participantMessageMongo;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $participantMessageId;
/**
* #Gedmo\ReferenceOne(type="document", class="xxx\MensajeriaBundle\Document\Thread", inversedBy="participants", identifier="participantsId")
*/
private $participantsMongo;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $participantsId;
/**
* #Gedmo\ReferenceOne(type="document", class="xxx\MensajeriaBundle\Document\Thread", inversedBy="createdBy", identifier="createdById")
*/
private $createdByMongo;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $createdById;
/**
* #Gedmo\ReferenceOne(type="document", class="xxx\MensajeriaBundle\Document\ThreadMetadata", inversedBy="participant", identifier="participantThreadId")
*/
private $participantThreadMongo;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $participantThreadId;
This is what you need, you can reference relationships between ODM and ORM entities https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/references.md