Hi Lucas, On Tue, Jul 19, 2011 at 10:49 PM, Lucas De Marchi <lucas.demarchi@xxxxxxxxxxxxxx> wrote: > --- > audio/control.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 86 insertions(+), 2 deletions(-) > > diff --git a/audio/control.c b/audio/control.c > index c3ef737..983c8cd 100644 > --- a/audio/control.c > +++ b/audio/control.c > @@ -102,6 +102,22 @@ > #define FORWARD_OP 0x4b > #define BACKWARD_OP 0x4c > > +/* Company IDs for vendor dependent commands */ > +#define IEEEID_BTSIG 0x001958 > + > +/* Error codes for metadata transfer */ > +#define E_INVALID_COMMAND 0x00 > +#define E_INVALID_PARAM 0x01 > +#define E_PARAM_NOT_FOUND 0x02 > +#define E_INTERNAL 0x03 > + > +/* PDU types for metadata transfer */ > +#define AVRCP_GET_CAPABILITIES 0x10 > + > +/* Capabilities for AVRCP_GET_CAPABILITIES pdu */ > +#define CAP_COMPANY_ID 0x02 > +#define CAP_EVENTS_SUPPORTED 0x03 > + > #define QUIRK_NO_RELEASE 1 << 0 > > static DBusConnection *connection = NULL; > @@ -217,6 +233,11 @@ static struct { > { NULL } > }; > > +/* Company IDs supported by this device */ > +static uint32_t company_ids[] = { > + IEEEID_BTSIG, > +}; > + > static GSList *avctp_callbacks = NULL; > > static void auth_cb(DBusError *derr, void *user_data); > @@ -424,8 +445,71 @@ static int handle_vendordep_pdu(struct control *control, > struct avrcp_header *avrcp, > int operand_count) > { > - avrcp->code = CTYPE_NOT_IMPLEMENTED; > - return AVRCP_HEADER_LENGTH; > + struct avrcp_spec_avc_pdu *pdu = (void *) avrcp + AVRCP_HEADER_LENGTH; > + uint32_t company_id = (pdu->company_id[0] << 16) | > + (pdu->company_id[1] << 8) | > + (pdu->company_id[2]); > + uint16_t len; > + unsigned int i; > + > + if (company_id != IEEEID_BTSIG || > + pdu->packet_type != AVCTP_PACKET_SINGLE) { > + avrcp->code = CTYPE_NOT_IMPLEMENTED; > + return AVRCP_HEADER_LENGTH; > + } > + > + pdu->packet_type = 0; > + pdu->rsvd = 0; > + > + if (operand_count + 3 < AVRCP_SPECAVCPDU_HEADER_LENGTH) { > + pdu->params[0] = E_INVALID_COMMAND; > + goto err_metadata; > + } > + > + len = ntohs(pdu->params_len); I would consider doing the each pdu handling in its own function, otherwise handle_vendordep_pdu might become a little too big. > + switch (pdu->pdu_id) { > + case AVRCP_GET_CAPABILITIES: > + if (len != 1 || avrcp->code != CTYPE_STATUS) > + break; > + > + DBG("GET_CAPABILITIES id=%u", pdu->params[0]); > + > + switch (pdu->params[0]) { /* capability id */ > + case CAP_COMPANY_ID: > + avrcp->code = CTYPE_STABLE; > + pdu->params_len = htons(1 + > + 3 * G_N_ELEMENTS(company_ids)); > + pdu->params[1] = G_N_ELEMENTS(company_ids); > + > + for (i = 0; i < G_N_ELEMENTS(company_ids); i++) { > + pdu->params[2 + i * 3] = company_ids[i] >> 16; > + pdu->params[3 + i * 3] = (company_ids[i] >> 8) > + & 0xFF; > + pdu->params[4 + i * 3] = company_ids[i] & 0xFF; > + } > + > + return AVRCP_HEADER_LENGTH + > + AVRCP_SPECAVCPDU_HEADER_LENGTH + 1 + > + 3 * G_N_ELEMENTS(company_ids); > + } > + > + pdu->params[0] = E_INVALID_PARAM; > + goto err_metadata; > + } > + > + /* > + * If either pdu_id was invalid or message was malformed, respond with > + * E_INVALID_COMMAND. For other errors, we already jumped into > + * err_metadata. > + */ > + pdu->params[0] = E_INVALID_COMMAND; > + > +err_metadata: > + avrcp->code = CTYPE_REJECTED; > + pdu->params_len = htons(1); > + > + return AVRCP_HEADER_LENGTH + AVRCP_SPECAVCPDU_HEADER_LENGTH + 1; > } > > static void avctp_disconnected(struct audio_device *dev) > -- > 1.7.6 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- Luiz Augusto von Dentz -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html