Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * oxfw_command.c - a part of driver for OXFW970/971 based devices
0004  *
0005  * Copyright (c) 2014 Takashi Sakamoto
0006  */
0007 
0008 #include "oxfw.h"
0009 
0010 int avc_stream_set_format(struct fw_unit *unit, enum avc_general_plug_dir dir,
0011               unsigned int pid, u8 *format, unsigned int len)
0012 {
0013     u8 *buf;
0014     int err;
0015 
0016     buf = kmalloc(len + 10, GFP_KERNEL);
0017     if (buf == NULL)
0018         return -ENOMEM;
0019 
0020     buf[0] = 0x00;      /* CONTROL */
0021     buf[1] = 0xff;      /* UNIT */
0022     buf[2] = 0xbf;      /* EXTENDED STREAM FORMAT INFORMATION */
0023     buf[3] = 0xc0;      /* SINGLE subfunction */
0024     buf[4] = dir;       /* Plug Direction */
0025     buf[5] = 0x00;      /* UNIT */
0026     buf[6] = 0x00;      /* PCR (Isochronous Plug) */
0027     buf[7] = 0xff & pid;    /* Plug ID */
0028     buf[8] = 0xff;      /* Padding */
0029     buf[9] = 0xff;      /* Support status in response */
0030     memcpy(buf + 10, format, len);
0031 
0032     /* do transaction and check buf[1-8] are the same against command */
0033     err = fcp_avc_transaction(unit, buf, len + 10, buf, len + 10,
0034                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0035                   BIT(6) | BIT(7) | BIT(8));
0036     if (err < 0)
0037         ;
0038     else if (err < len + 10)
0039         err = -EIO;
0040     else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
0041         err = -ENXIO;
0042     else if (buf[0] == 0x0a) /* REJECTED */
0043         err = -EINVAL;
0044     else
0045         err = 0;
0046 
0047     kfree(buf);
0048 
0049     return err;
0050 }
0051 
0052 int avc_stream_get_format(struct fw_unit *unit,
0053               enum avc_general_plug_dir dir, unsigned int pid,
0054               u8 *buf, unsigned int *len, unsigned int eid)
0055 {
0056     unsigned int subfunc;
0057     int err;
0058 
0059     if (eid == 0xff)
0060         subfunc = 0xc0; /* SINGLE */
0061     else
0062         subfunc = 0xc1; /* LIST */
0063 
0064     buf[0] = 0x01;      /* STATUS */
0065     buf[1] = 0xff;      /* UNIT */
0066     buf[2] = 0xbf;      /* EXTENDED STREAM FORMAT INFORMATION */
0067     buf[3] = subfunc;   /* SINGLE or LIST */
0068     buf[4] = dir;       /* Plug Direction */
0069     buf[5] = 0x00;      /* Unit */
0070     buf[6] = 0x00;      /* PCR (Isochronous Plug) */
0071     buf[7] = 0xff & pid;    /* Plug ID */
0072     buf[8] = 0xff;      /* Padding */
0073     buf[9] = 0xff;      /* support status in response */
0074     buf[10] = 0xff & eid;   /* entry ID for LIST subfunction */
0075     buf[11] = 0xff;     /* padding */
0076 
0077     /* do transaction and check buf[1-7] are the same against command */
0078     err = fcp_avc_transaction(unit, buf, 12, buf, *len,
0079                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
0080                   BIT(6) | BIT(7));
0081     if (err < 0)
0082         ;
0083     else if (err < 12)
0084         err = -EIO;
0085     else if (buf[0] == 0x08)    /* NOT IMPLEMENTED */
0086         err = -ENXIO;
0087     else if (buf[0] == 0x0a)    /* REJECTED */
0088         err = -EINVAL;
0089     else if (buf[0] == 0x0b)    /* IN TRANSITION */
0090         err = -EAGAIN;
0091     /* LIST subfunction has entry ID */
0092     else if ((subfunc == 0xc1) && (buf[10] != eid))
0093         err = -EIO;
0094     if (err < 0)
0095         goto end;
0096 
0097     /* keep just stream format information */
0098     if (subfunc == 0xc0) {
0099         memmove(buf, buf + 10, err - 10);
0100         *len = err - 10;
0101     } else {
0102         memmove(buf, buf + 11, err - 11);
0103         *len = err - 11;
0104     }
0105 
0106     err = 0;
0107 end:
0108     return err;
0109 }
0110 
0111 int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate,
0112                 enum avc_general_plug_dir dir,
0113                 unsigned short pid)
0114 {
0115     unsigned int sfc;
0116     u8 *buf;
0117     int err;
0118 
0119     for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) {
0120         if (amdtp_rate_table[sfc] == rate)
0121             break;
0122     }
0123     if (sfc == CIP_SFC_COUNT)
0124         return -EINVAL;
0125 
0126     buf = kzalloc(8, GFP_KERNEL);
0127     if (buf == NULL)
0128         return -ENOMEM;
0129 
0130     buf[0] = 0x02;      /* SPECIFIC INQUIRY */
0131     buf[1] = 0xff;      /* UNIT */
0132     if (dir == AVC_GENERAL_PLUG_DIR_IN)
0133         buf[2] = 0x19;  /* INPUT PLUG SIGNAL FORMAT */
0134     else
0135         buf[2] = 0x18;  /* OUTPUT PLUG SIGNAL FORMAT */
0136     buf[3] = 0xff & pid;    /* plug id */
0137     buf[4] = 0x90;      /* EOH_1, Form_1, FMT. AM824 */
0138     buf[5] = 0x07 & sfc;    /* FDF-hi. AM824, frequency */
0139     buf[6] = 0xff;      /* FDF-mid. AM824, SYT hi (not used) */
0140     buf[7] = 0xff;      /* FDF-low. AM824, SYT lo (not used) */
0141 
0142     /* do transaction and check buf[1-5] are the same against command */
0143     err = fcp_avc_transaction(unit, buf, 8, buf, 8,
0144                   BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
0145     if (err < 0)
0146         ;
0147     else if (err < 8)
0148         err = -EIO;
0149     else if (buf[0] == 0x08)    /* NOT IMPLEMENTED */
0150         err = -ENXIO;
0151     if (err < 0)
0152         goto end;
0153 
0154     err = 0;
0155 end:
0156     kfree(buf);
0157     return err;
0158 }