1eb7b3a05STakashi Sakamoto /* 2eb7b3a05STakashi Sakamoto * bebob_command.c - driver for BeBoB based devices 3eb7b3a05STakashi Sakamoto * 4eb7b3a05STakashi Sakamoto * Copyright (c) 2013-2014 Takashi Sakamoto 5eb7b3a05STakashi Sakamoto * 6eb7b3a05STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 7eb7b3a05STakashi Sakamoto */ 8eb7b3a05STakashi Sakamoto 9eb7b3a05STakashi Sakamoto #include "./bebob.h" 10eb7b3a05STakashi Sakamoto 11eb7b3a05STakashi Sakamoto static inline void 12eb7b3a05STakashi Sakamoto avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr) 13eb7b3a05STakashi Sakamoto { 14eb7b3a05STakashi Sakamoto buf[1] = addr[0]; 15eb7b3a05STakashi Sakamoto memcpy(buf + 4, addr + 1, 5); 16eb7b3a05STakashi Sakamoto } 17eb7b3a05STakashi Sakamoto 18eb7b3a05STakashi Sakamoto static inline void 19eb7b3a05STakashi Sakamoto avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr, 20eb7b3a05STakashi Sakamoto unsigned int itype) 21eb7b3a05STakashi Sakamoto { 22eb7b3a05STakashi Sakamoto buf[0] = 0x01; /* AV/C STATUS */ 23eb7b3a05STakashi Sakamoto buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */ 24eb7b3a05STakashi Sakamoto buf[3] = 0xc0; /* BridgeCo extension */ 25eb7b3a05STakashi Sakamoto avc_bridgeco_fill_extension_addr(buf, addr); 26eb7b3a05STakashi Sakamoto buf[9] = itype; /* info type */ 27eb7b3a05STakashi Sakamoto } 28eb7b3a05STakashi Sakamoto 29eb7b3a05STakashi Sakamoto int avc_bridgeco_get_plug_type(struct fw_unit *unit, 30eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], 31eb7b3a05STakashi Sakamoto enum avc_bridgeco_plug_type *type) 32eb7b3a05STakashi Sakamoto { 33eb7b3a05STakashi Sakamoto u8 *buf; 34eb7b3a05STakashi Sakamoto int err; 35eb7b3a05STakashi Sakamoto 36eb7b3a05STakashi Sakamoto buf = kzalloc(12, GFP_KERNEL); 37eb7b3a05STakashi Sakamoto if (buf == NULL) 38eb7b3a05STakashi Sakamoto return -ENOMEM; 39eb7b3a05STakashi Sakamoto 40eb7b3a05STakashi Sakamoto /* Info type is 'plug type'. */ 41eb7b3a05STakashi Sakamoto avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00); 42eb7b3a05STakashi Sakamoto 43eb7b3a05STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 12, buf, 12, 44eb7b3a05STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 45eb7b3a05STakashi Sakamoto BIT(6) | BIT(7) | BIT(9)); 46eb7b3a05STakashi Sakamoto if ((err >= 0) && (err < 8)) 47eb7b3a05STakashi Sakamoto err = -EIO; 48eb7b3a05STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 49eb7b3a05STakashi Sakamoto err = -ENOSYS; 50eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 51eb7b3a05STakashi Sakamoto err = -EINVAL; 52eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0b) /* IN TRANSITION */ 53eb7b3a05STakashi Sakamoto err = -EAGAIN; 54eb7b3a05STakashi Sakamoto if (err < 0) 55eb7b3a05STakashi Sakamoto goto end; 56eb7b3a05STakashi Sakamoto 57eb7b3a05STakashi Sakamoto *type = buf[10]; 58eb7b3a05STakashi Sakamoto err = 0; 59eb7b3a05STakashi Sakamoto end: 60eb7b3a05STakashi Sakamoto kfree(buf); 61eb7b3a05STakashi Sakamoto return err; 62eb7b3a05STakashi Sakamoto } 63eb7b3a05STakashi Sakamoto 64eb7b3a05STakashi Sakamoto int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit, 65eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], 66eb7b3a05STakashi Sakamoto u8 *buf, unsigned int len) 67eb7b3a05STakashi Sakamoto { 68eb7b3a05STakashi Sakamoto int err; 69eb7b3a05STakashi Sakamoto 70eb7b3a05STakashi Sakamoto /* Info type is 'channel position'. */ 71eb7b3a05STakashi Sakamoto avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03); 72eb7b3a05STakashi Sakamoto 73eb7b3a05STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 12, buf, 256, 74eb7b3a05STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | 75eb7b3a05STakashi Sakamoto BIT(5) | BIT(6) | BIT(7) | BIT(9)); 76eb7b3a05STakashi Sakamoto if ((err >= 0) && (err < 8)) 77eb7b3a05STakashi Sakamoto err = -EIO; 78eb7b3a05STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 79eb7b3a05STakashi Sakamoto err = -ENOSYS; 80eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 81eb7b3a05STakashi Sakamoto err = -EINVAL; 82eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0b) /* IN TRANSITION */ 83eb7b3a05STakashi Sakamoto err = -EAGAIN; 84eb7b3a05STakashi Sakamoto if (err < 0) 85eb7b3a05STakashi Sakamoto goto end; 86eb7b3a05STakashi Sakamoto 87eb7b3a05STakashi Sakamoto /* Pick up specific data. */ 88eb7b3a05STakashi Sakamoto memmove(buf, buf + 10, err - 10); 89eb7b3a05STakashi Sakamoto err = 0; 90eb7b3a05STakashi Sakamoto end: 91eb7b3a05STakashi Sakamoto return err; 92eb7b3a05STakashi Sakamoto } 93eb7b3a05STakashi Sakamoto 94eb7b3a05STakashi Sakamoto int avc_bridgeco_get_plug_section_type(struct fw_unit *unit, 95eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], 96eb7b3a05STakashi Sakamoto unsigned int id, u8 *type) 97eb7b3a05STakashi Sakamoto { 98eb7b3a05STakashi Sakamoto u8 *buf; 99eb7b3a05STakashi Sakamoto int err; 100eb7b3a05STakashi Sakamoto 101eb7b3a05STakashi Sakamoto /* section info includes charactors but this module don't need it */ 102eb7b3a05STakashi Sakamoto buf = kzalloc(12, GFP_KERNEL); 103eb7b3a05STakashi Sakamoto if (buf == NULL) 104eb7b3a05STakashi Sakamoto return -ENOMEM; 105eb7b3a05STakashi Sakamoto 106eb7b3a05STakashi Sakamoto /* Info type is 'section info'. */ 107eb7b3a05STakashi Sakamoto avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07); 108eb7b3a05STakashi Sakamoto buf[10] = 0xff & ++id; /* section id */ 109eb7b3a05STakashi Sakamoto 110eb7b3a05STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 12, buf, 12, 111eb7b3a05STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 112eb7b3a05STakashi Sakamoto BIT(6) | BIT(7) | BIT(9) | BIT(10)); 113eb7b3a05STakashi Sakamoto if ((err >= 0) && (err < 8)) 114eb7b3a05STakashi Sakamoto err = -EIO; 115eb7b3a05STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 116eb7b3a05STakashi Sakamoto err = -ENOSYS; 117eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 118eb7b3a05STakashi Sakamoto err = -EINVAL; 119eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0b) /* IN TRANSITION */ 120eb7b3a05STakashi Sakamoto err = -EAGAIN; 121eb7b3a05STakashi Sakamoto if (err < 0) 122eb7b3a05STakashi Sakamoto goto end; 123eb7b3a05STakashi Sakamoto 124eb7b3a05STakashi Sakamoto *type = buf[11]; 125eb7b3a05STakashi Sakamoto err = 0; 126eb7b3a05STakashi Sakamoto end: 127eb7b3a05STakashi Sakamoto kfree(buf); 128eb7b3a05STakashi Sakamoto return err; 129eb7b3a05STakashi Sakamoto } 130eb7b3a05STakashi Sakamoto 131eb7b3a05STakashi Sakamoto int avc_bridgeco_get_plug_input(struct fw_unit *unit, 132eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7]) 133eb7b3a05STakashi Sakamoto { 134eb7b3a05STakashi Sakamoto int err; 135eb7b3a05STakashi Sakamoto u8 *buf; 136eb7b3a05STakashi Sakamoto 137eb7b3a05STakashi Sakamoto buf = kzalloc(18, GFP_KERNEL); 138eb7b3a05STakashi Sakamoto if (buf == NULL) 139eb7b3a05STakashi Sakamoto return -ENOMEM; 140eb7b3a05STakashi Sakamoto 141eb7b3a05STakashi Sakamoto /* Info type is 'plug input'. */ 142eb7b3a05STakashi Sakamoto avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05); 143eb7b3a05STakashi Sakamoto 144eb7b3a05STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 16, buf, 16, 145eb7b3a05STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 146eb7b3a05STakashi Sakamoto BIT(6) | BIT(7)); 147eb7b3a05STakashi Sakamoto if ((err >= 0) && (err < 8)) 148eb7b3a05STakashi Sakamoto err = -EIO; 149eb7b3a05STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 150eb7b3a05STakashi Sakamoto err = -ENOSYS; 151eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 152eb7b3a05STakashi Sakamoto err = -EINVAL; 153eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0b) /* IN TRANSITION */ 154eb7b3a05STakashi Sakamoto err = -EAGAIN; 155eb7b3a05STakashi Sakamoto if (err < 0) 156eb7b3a05STakashi Sakamoto goto end; 157eb7b3a05STakashi Sakamoto 158eb7b3a05STakashi Sakamoto memcpy(input, buf + 10, 5); 159eb7b3a05STakashi Sakamoto err = 0; 160eb7b3a05STakashi Sakamoto end: 161eb7b3a05STakashi Sakamoto kfree(buf); 162eb7b3a05STakashi Sakamoto return err; 163eb7b3a05STakashi Sakamoto } 164eb7b3a05STakashi Sakamoto 165eb7b3a05STakashi Sakamoto int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit, 166eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf, 167eb7b3a05STakashi Sakamoto unsigned int *len, unsigned int eid) 168eb7b3a05STakashi Sakamoto { 169eb7b3a05STakashi Sakamoto int err; 170eb7b3a05STakashi Sakamoto 171eb7b3a05STakashi Sakamoto /* check given buffer */ 172eb7b3a05STakashi Sakamoto if ((buf == NULL) || (*len < 12)) { 173eb7b3a05STakashi Sakamoto err = -EINVAL; 174eb7b3a05STakashi Sakamoto goto end; 175eb7b3a05STakashi Sakamoto } 176eb7b3a05STakashi Sakamoto 177eb7b3a05STakashi Sakamoto buf[0] = 0x01; /* AV/C STATUS */ 178eb7b3a05STakashi Sakamoto buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */ 179eb7b3a05STakashi Sakamoto buf[3] = 0xc1; /* Bridgeco extension - List Request */ 180eb7b3a05STakashi Sakamoto avc_bridgeco_fill_extension_addr(buf, addr); 181eb7b3a05STakashi Sakamoto buf[10] = 0xff & eid; /* Entry ID */ 182eb7b3a05STakashi Sakamoto 183eb7b3a05STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 12, buf, *len, 184eb7b3a05STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 185eb7b3a05STakashi Sakamoto BIT(6) | BIT(7) | BIT(10)); 186eb7b3a05STakashi Sakamoto if ((err >= 0) && (err < 12)) 187eb7b3a05STakashi Sakamoto err = -EIO; 188eb7b3a05STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 189eb7b3a05STakashi Sakamoto err = -ENOSYS; 190eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 191eb7b3a05STakashi Sakamoto err = -EINVAL; 192eb7b3a05STakashi Sakamoto else if (buf[0] == 0x0b) /* IN TRANSITION */ 193eb7b3a05STakashi Sakamoto err = -EAGAIN; 194eb7b3a05STakashi Sakamoto else if (buf[10] != eid) 195eb7b3a05STakashi Sakamoto err = -EIO; 196eb7b3a05STakashi Sakamoto if (err < 0) 197eb7b3a05STakashi Sakamoto goto end; 198eb7b3a05STakashi Sakamoto 199eb7b3a05STakashi Sakamoto /* Pick up 'stream format info'. */ 200eb7b3a05STakashi Sakamoto memmove(buf, buf + 11, err - 11); 201eb7b3a05STakashi Sakamoto *len = err - 11; 202eb7b3a05STakashi Sakamoto err = 0; 203eb7b3a05STakashi Sakamoto end: 204eb7b3a05STakashi Sakamoto return err; 205eb7b3a05STakashi Sakamoto } 206