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