1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * oxfw_command.c - a part of driver for OXFW970/971 based devices 4 * 5 * Copyright (c) 2014 Takashi Sakamoto 6 */ 7 8 #include "oxfw.h" 9 10 int avc_stream_set_format(struct fw_unit *unit, enum avc_general_plug_dir dir, 11 unsigned int pid, u8 *format, unsigned int len) 12 { 13 u8 *buf; 14 int err; 15 16 buf = kmalloc(len + 10, GFP_KERNEL); 17 if (buf == NULL) 18 return -ENOMEM; 19 20 buf[0] = 0x00; /* CONTROL */ 21 buf[1] = 0xff; /* UNIT */ 22 buf[2] = 0xbf; /* EXTENDED STREAM FORMAT INFORMATION */ 23 buf[3] = 0xc0; /* SINGLE subfunction */ 24 buf[4] = dir; /* Plug Direction */ 25 buf[5] = 0x00; /* UNIT */ 26 buf[6] = 0x00; /* PCR (Isochronous Plug) */ 27 buf[7] = 0xff & pid; /* Plug ID */ 28 buf[8] = 0xff; /* Padding */ 29 buf[9] = 0xff; /* Support status in response */ 30 memcpy(buf + 10, format, len); 31 32 /* do transaction and check buf[1-8] are the same against command */ 33 err = fcp_avc_transaction(unit, buf, len + 10, buf, len + 10, 34 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 35 BIT(6) | BIT(7) | BIT(8)); 36 if (err < 0) 37 ; 38 else if (err < len + 10) 39 err = -EIO; 40 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 41 err = -ENOSYS; 42 else if (buf[0] == 0x0a) /* REJECTED */ 43 err = -EINVAL; 44 else 45 err = 0; 46 47 kfree(buf); 48 49 return err; 50 } 51 52 int avc_stream_get_format(struct fw_unit *unit, 53 enum avc_general_plug_dir dir, unsigned int pid, 54 u8 *buf, unsigned int *len, unsigned int eid) 55 { 56 unsigned int subfunc; 57 int err; 58 59 if (eid == 0xff) 60 subfunc = 0xc0; /* SINGLE */ 61 else 62 subfunc = 0xc1; /* LIST */ 63 64 buf[0] = 0x01; /* STATUS */ 65 buf[1] = 0xff; /* UNIT */ 66 buf[2] = 0xbf; /* EXTENDED STREAM FORMAT INFORMATION */ 67 buf[3] = subfunc; /* SINGLE or LIST */ 68 buf[4] = dir; /* Plug Direction */ 69 buf[5] = 0x00; /* Unit */ 70 buf[6] = 0x00; /* PCR (Isochronous Plug) */ 71 buf[7] = 0xff & pid; /* Plug ID */ 72 buf[8] = 0xff; /* Padding */ 73 buf[9] = 0xff; /* support status in response */ 74 buf[10] = 0xff & eid; /* entry ID for LIST subfunction */ 75 buf[11] = 0xff; /* padding */ 76 77 /* do transaction and check buf[1-7] are the same against command */ 78 err = fcp_avc_transaction(unit, buf, 12, buf, *len, 79 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 80 BIT(6) | BIT(7)); 81 if (err < 0) 82 ; 83 else if (err < 12) 84 err = -EIO; 85 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 86 err = -ENOSYS; 87 else if (buf[0] == 0x0a) /* REJECTED */ 88 err = -EINVAL; 89 else if (buf[0] == 0x0b) /* IN TRANSITION */ 90 err = -EAGAIN; 91 /* LIST subfunction has entry ID */ 92 else if ((subfunc == 0xc1) && (buf[10] != eid)) 93 err = -EIO; 94 if (err < 0) 95 goto end; 96 97 /* keep just stream format information */ 98 if (subfunc == 0xc0) { 99 memmove(buf, buf + 10, err - 10); 100 *len = err - 10; 101 } else { 102 memmove(buf, buf + 11, err - 11); 103 *len = err - 11; 104 } 105 106 err = 0; 107 end: 108 return err; 109 } 110 111 int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate, 112 enum avc_general_plug_dir dir, 113 unsigned short pid) 114 { 115 unsigned int sfc; 116 u8 *buf; 117 int err; 118 119 for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) { 120 if (amdtp_rate_table[sfc] == rate) 121 break; 122 } 123 if (sfc == CIP_SFC_COUNT) 124 return -EINVAL; 125 126 buf = kzalloc(8, GFP_KERNEL); 127 if (buf == NULL) 128 return -ENOMEM; 129 130 buf[0] = 0x02; /* SPECIFIC INQUIRY */ 131 buf[1] = 0xff; /* UNIT */ 132 if (dir == AVC_GENERAL_PLUG_DIR_IN) 133 buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ 134 else 135 buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */ 136 buf[3] = 0xff & pid; /* plug id */ 137 buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */ 138 buf[5] = 0x07 & sfc; /* FDF-hi. AM824, frequency */ 139 buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used) */ 140 buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */ 141 142 /* do transaction and check buf[1-5] are the same against command */ 143 err = fcp_avc_transaction(unit, buf, 8, buf, 8, 144 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); 145 if (err < 0) 146 ; 147 else if (err < 8) 148 err = -EIO; 149 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 150 err = -ENOSYS; 151 if (err < 0) 152 goto end; 153 154 err = 0; 155 end: 156 kfree(buf); 157 return err; 158 } 159