Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * bebob_command.c - driver for BeBoB based devices
0004  *
0005  * Copyright (c) 2013-2014 Takashi Sakamoto
0006  */
0007 
0008 #include "./bebob.h"
0009 
0010 int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
0011                unsigned int fb_id, unsigned int num)
0012 {
0013     u8 *buf;
0014     int err;
0015 
0016     buf = kzalloc(12, GFP_KERNEL);
0017     if (buf == NULL)
0018         return -ENOMEM;
0019 
0020     buf[0]  = 0x00;     /* AV/C CONTROL */
0021     buf[1]  = 0x08 | (0x07 & subunit_id);   /* AUDIO SUBUNIT ID */
0022     buf[2]  = 0xb8;     /* FUNCTION BLOCK  */
0023     buf[3]  = 0x80;     /* type is 'selector'*/
0024     buf[4]  = 0xff & fb_id; /* function block id */
0025     buf[5]  = 0x10;     /* control attribute is CURRENT */
0026     buf[6]  = 0x02;     /* selector length is 2 */
0027     buf[7]  = 0xff & num;   /* input function block plug number */
0028     buf[8]  = 0x01;     /* control selector is SELECTOR_CONTROL */
0029 
0030     err = fcp_avc_transaction(unit, buf, 12, buf, 12,
0031                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0032                   BIT(6) | BIT(7) | BIT(8));
0033     if (err < 0)
0034         ;
0035     else if (err < 9)
0036         err = -EIO;
0037     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0038         err = -ENOSYS;
0039     else if (buf[0] == 0x0a) /* REJECTED */
0040         err = -EINVAL;
0041     else
0042         err = 0;
0043 
0044     kfree(buf);
0045     return err;
0046 }
0047 
0048 int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
0049                unsigned int fb_id, unsigned int *num)
0050 {
0051     u8 *buf;
0052     int err;
0053 
0054     buf = kzalloc(12, GFP_KERNEL);
0055     if (buf == NULL)
0056         return -ENOMEM;
0057 
0058     buf[0]  = 0x01;     /* AV/C STATUS */
0059     buf[1]  = 0x08 | (0x07 & subunit_id);   /* AUDIO SUBUNIT ID */
0060     buf[2]  = 0xb8;     /* FUNCTION BLOCK */
0061     buf[3]  = 0x80;     /* type is 'selector'*/
0062     buf[4]  = 0xff & fb_id; /* function block id */
0063     buf[5]  = 0x10;     /* control attribute is CURRENT */
0064     buf[6]  = 0x02;     /* selector length is 2 */
0065     buf[7]  = 0xff;     /* input function block plug number */
0066     buf[8]  = 0x01;     /* control selector is SELECTOR_CONTROL */
0067 
0068     err = fcp_avc_transaction(unit, buf, 12, buf, 12,
0069                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0070                   BIT(6) | BIT(8));
0071     if (err < 0)
0072         ;
0073     else if (err < 9)
0074         err = -EIO;
0075     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0076         err = -ENOSYS;
0077     else if (buf[0] == 0x0a) /* REJECTED */
0078         err = -EINVAL;
0079     else if (buf[0] == 0x0b) /* IN TRANSITION */
0080         err = -EAGAIN;
0081     if (err < 0)
0082         goto end;
0083 
0084     *num = buf[7];
0085     err = 0;
0086 end:
0087     kfree(buf);
0088     return err;
0089 }
0090 
0091 static inline void
0092 avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
0093 {
0094     buf[1] = addr[0];
0095     memcpy(buf + 4, addr + 1, 5);
0096 }
0097 
0098 static inline void
0099 avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
0100                           unsigned int itype)
0101 {
0102     buf[0] = 0x01;  /* AV/C STATUS */
0103     buf[2] = 0x02;  /* AV/C GENERAL PLUG INFO */
0104     buf[3] = 0xc0;  /* BridgeCo extension */
0105     avc_bridgeco_fill_extension_addr(buf, addr);
0106     buf[9] = itype; /* info type */
0107 }
0108 
0109 int avc_bridgeco_get_plug_type(struct fw_unit *unit,
0110                    u8 addr[AVC_BRIDGECO_ADDR_BYTES],
0111                    enum avc_bridgeco_plug_type *type)
0112 {
0113     u8 *buf;
0114     int err;
0115 
0116     buf = kzalloc(12, GFP_KERNEL);
0117     if (buf == NULL)
0118         return -ENOMEM;
0119 
0120     /* Info type is 'plug type'. */
0121     avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
0122 
0123     err = fcp_avc_transaction(unit, buf, 12, buf, 12,
0124                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0125                   BIT(6) | BIT(7) | BIT(9));
0126     if (err < 0)
0127         ;
0128     else if (err < 11)
0129         err = -EIO;
0130     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0131         err = -ENOSYS;
0132     else if (buf[0] == 0x0a) /* REJECTED */
0133         err = -EINVAL;
0134     else if (buf[0] == 0x0b) /* IN TRANSITION */
0135         err = -EAGAIN;
0136     if (err < 0)
0137         goto end;
0138 
0139     *type = buf[10];
0140     err = 0;
0141 end:
0142     kfree(buf);
0143     return err;
0144 }
0145 
0146 int avc_bridgeco_get_plug_ch_count(struct fw_unit *unit, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
0147                    unsigned int *ch_count)
0148 {
0149     u8 *buf;
0150     int err;
0151 
0152     buf = kzalloc(12, GFP_KERNEL);
0153     if (buf == NULL)
0154         return -ENOMEM;
0155 
0156     // Info type is 'plug type'.
0157     avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x02);
0158 
0159     err = fcp_avc_transaction(unit, buf, 12, buf, 12,
0160                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0161                   BIT(6) | BIT(7) | BIT(9));
0162     if (err < 0)
0163         ;
0164     else if (err < 11)
0165         err = -EIO;
0166     else if (buf[0] == 0x08) // NOT IMPLEMENTED
0167         err = -ENOSYS;
0168     else if (buf[0] == 0x0a) // REJECTED
0169         err = -EINVAL;
0170     else if (buf[0] == 0x0b) // IN TRANSITION
0171         err = -EAGAIN;
0172     if (err < 0)
0173         goto end;
0174 
0175     *ch_count = buf[10];
0176     err = 0;
0177 end:
0178     kfree(buf);
0179     return err;
0180 }
0181 
0182 int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
0183                  u8 addr[AVC_BRIDGECO_ADDR_BYTES],
0184                  u8 *buf, unsigned int len)
0185 {
0186     int err;
0187 
0188     /* Info type is 'channel position'. */
0189     avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
0190 
0191     err = fcp_avc_transaction(unit, buf, 12, buf, 256,
0192                   BIT(1) | BIT(2) | BIT(3) | BIT(4) |
0193                   BIT(5) | BIT(6) | BIT(7) | BIT(9));
0194     if (err < 0)
0195         ;
0196     else if (err < 11)
0197         err = -EIO;
0198     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0199         err = -ENOSYS;
0200     else if (buf[0] == 0x0a) /* REJECTED */
0201         err = -EINVAL;
0202     else if (buf[0] == 0x0b) /* IN TRANSITION */
0203         err = -EAGAIN;
0204     if (err < 0)
0205         goto end;
0206 
0207     /* Pick up specific data. */
0208     memmove(buf, buf + 10, err - 10);
0209     err = 0;
0210 end:
0211     return err;
0212 }
0213 
0214 int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
0215                        u8 addr[AVC_BRIDGECO_ADDR_BYTES],
0216                        unsigned int id, u8 *type)
0217 {
0218     u8 *buf;
0219     int err;
0220 
0221     /* section info includes charactors but this module don't need it */
0222     buf = kzalloc(12, GFP_KERNEL);
0223     if (buf == NULL)
0224         return -ENOMEM;
0225 
0226     /* Info type is 'section info'. */
0227     avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
0228     buf[10] = 0xff & ++id;  /* section id */
0229 
0230     err = fcp_avc_transaction(unit, buf, 12, buf, 12,
0231                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0232                   BIT(6) | BIT(7) | BIT(9) | BIT(10));
0233     if (err < 0)
0234         ;
0235     else if (err < 12)
0236         err = -EIO;
0237     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0238         err = -ENOSYS;
0239     else if (buf[0] == 0x0a) /* REJECTED */
0240         err = -EINVAL;
0241     else if (buf[0] == 0x0b) /* IN TRANSITION */
0242         err = -EAGAIN;
0243     if (err < 0)
0244         goto end;
0245 
0246     *type = buf[11];
0247     err = 0;
0248 end:
0249     kfree(buf);
0250     return err;
0251 }
0252 
0253 int avc_bridgeco_get_plug_input(struct fw_unit *unit,
0254                 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
0255 {
0256     int err;
0257     u8 *buf;
0258 
0259     buf = kzalloc(18, GFP_KERNEL);
0260     if (buf == NULL)
0261         return -ENOMEM;
0262 
0263     /* Info type is 'plug input'. */
0264     avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
0265 
0266     err = fcp_avc_transaction(unit, buf, 16, buf, 16,
0267                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0268                   BIT(6) | BIT(7));
0269     if (err < 0)
0270         ;
0271     else if (err < 16)
0272         err = -EIO;
0273     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0274         err = -ENOSYS;
0275     else if (buf[0] == 0x0a) /* REJECTED */
0276         err = -EINVAL;
0277     else if (buf[0] == 0x0b) /* IN TRANSITION */
0278         err = -EAGAIN;
0279     if (err < 0)
0280         goto end;
0281 
0282     memcpy(input, buf + 10, 5);
0283     err = 0;
0284 end:
0285     kfree(buf);
0286     return err;
0287 }
0288 
0289 int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
0290                    u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
0291                    unsigned int *len, unsigned int eid)
0292 {
0293     int err;
0294 
0295     /* check given buffer */
0296     if ((buf == NULL) || (*len < 12)) {
0297         err = -EINVAL;
0298         goto end;
0299     }
0300 
0301     buf[0] = 0x01;  /* AV/C STATUS */
0302     buf[2] = 0x2f;  /* AV/C STREAM FORMAT SUPPORT */
0303     buf[3] = 0xc1;  /* Bridgeco extension - List Request */
0304     avc_bridgeco_fill_extension_addr(buf, addr);
0305     buf[10] = 0xff & eid;   /* Entry ID */
0306 
0307     err = fcp_avc_transaction(unit, buf, 12, buf, *len,
0308                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0309                   BIT(6) | BIT(7) | BIT(10));
0310     if (err < 0)
0311         ;
0312     else if (err < 12)
0313         err = -EIO;
0314     else if (buf[0] == 0x08)        /* NOT IMPLEMENTED */
0315         err = -ENOSYS;
0316     else if (buf[0] == 0x0a)        /* REJECTED */
0317         err = -EINVAL;
0318     else if (buf[0] == 0x0b)        /* IN TRANSITION */
0319         err = -EAGAIN;
0320     else if (buf[10] != eid)
0321         err = -EIO;
0322     if (err < 0)
0323         goto end;
0324 
0325     /* Pick up 'stream format info'. */
0326     memmove(buf, buf + 11, err - 11);
0327     *len = err - 11;
0328     err = 0;
0329 end:
0330     return err;
0331 }