1*84e33947SAndroid Build Coastguard Worker# CHRE API Parser + Code Generator for CHPP 2*84e33947SAndroid Build Coastguard Worker 3*84e33947SAndroid Build Coastguard WorkerSince one of the main use cases of CHPP is to support remoting a CHRE PAL 4*84e33947SAndroid Build Coastguard Workerimplementation to a peripheral component, we leverage the CHRE PAL API 5*84e33947SAndroid Build Coastguard Workerdefinitions for the platform-specific implementation of those services, such 6*84e33947SAndroid Build Coastguard Workeras the WWAN service. However, the structures used in the CHRE PAL APIs are the 7*84e33947SAndroid Build Coastguard Workersame as those used in the CHRE API for nanoapps, which are not inherently 8*84e33947SAndroid Build Coastguard Workerserializable, as they include things like pointers to other structures. So we 9*84e33947SAndroid Build Coastguard Workermust create slightly updated versions of these to send over the wire with CHPP. 10*84e33947SAndroid Build Coastguard Worker 11*84e33947SAndroid Build Coastguard WorkerThe `chre_api_to_chpp.py` script in this directory parses CHRE APIs according 12*84e33947SAndroid Build Coastguard Workerto instructions given in `chre_api_annotations.json` and generates structures 13*84e33947SAndroid Build Coastguard Workerand conversion code used for serialization and deserialization. 14*84e33947SAndroid Build Coastguard Worker 15*84e33947SAndroid Build Coastguard Worker## Serialization format 16*84e33947SAndroid Build Coastguard Worker 17*84e33947SAndroid Build Coastguard Worker_TL;DR: The CHPP format is just a packed and flattened version of the CHRE 18*84e33947SAndroid Build Coastguard Workerstructures, replacing pointers with offsets._ 19*84e33947SAndroid Build Coastguard Worker 20*84e33947SAndroid Build Coastguard WorkerThe serialized output is meant to match the source CHRE structure as closely as 21*84e33947SAndroid Build Coastguard Workerpossible, however some special handling is needed to be able to send them over 22*84e33947SAndroid Build Coastguard Workerthe wire to a different processor in the system. The general process for 23*84e33947SAndroid Build Coastguard Worker generating a serializable CHPP version of a CHRE structure is as follows: 24*84e33947SAndroid Build Coastguard Worker 25*84e33947SAndroid Build Coastguard Worker 1. Rewrite the name to start with "Chpp" instead of "chre" and mark it packed, 26*84e33947SAndroid Build Coastguard Worker to ensure there's no padding between fields (which is compiler-dependent) 27*84e33947SAndroid Build Coastguard Worker 1. Flatten the structure by replacing pointers to nested structures/arrays with 28*84e33947SAndroid Build Coastguard Worker a ChppOffset which describes the location in the payload where the nested 29*84e33947SAndroid Build Coastguard Worker data resides. 30*84e33947SAndroid Build Coastguard Worker 1. A CHPP application layer header is allocated for convenience when used in 31*84e33947SAndroid Build Coastguard Worker CHPP. The header values need to be set by CHPP and they are not zeroed out. 32*84e33947SAndroid Build Coastguard Worker The header length is not included in the offset calculation. 33*84e33947SAndroid Build Coastguard Worker 34*84e33947SAndroid Build Coastguard WorkerChppOffset is a collection of a 16-bit offset from the beginning of the payload, 35*84e33947SAndroid Build Coastguard Workerand a length. While we could implicitly derive the offset, the length cannot 36*84e33947SAndroid Build Coastguard Workerexceed 16 bits due to limitations in the encapsulating CHPP protocol 37*84e33947SAndroid Build Coastguard Worker(and we don't expect to bump up against this limit anyways), and including the 38*84e33947SAndroid Build Coastguard Workeroffset field helps simplify decoding. 39*84e33947SAndroid Build Coastguard Worker 40*84e33947SAndroid Build Coastguard WorkerThis approach allows for a highly optimized, in-place encoding and decoding that 41*84e33947SAndroid Build Coastguard Workeronly requires converting between pointer and ChppOffset types, if the following 42*84e33947SAndroid Build Coastguard Workerconditions are met: 43*84e33947SAndroid Build Coastguard Worker 44*84e33947SAndroid Build Coastguard Worker 1. The size of the CHRE and CHPP structures are the same, and the offsets to 45*84e33947SAndroid Build Coastguard Worker all contained fields are the same, and the same property holds for all 46*84e33947SAndroid Build Coastguard Worker nested structures/unions 47*84e33947SAndroid Build Coastguard Worker 1. (Encoding only) All nested structures appear in contiguous memory - for 48*84e33947SAndroid Build Coastguard Worker example, if a structure has a pointer to an array, then the array appears 49*84e33947SAndroid Build Coastguard Worker immediately after the structure in memory, with no padding 50*84e33947SAndroid Build Coastguard Worker 1. (Decoding only) Processor alignment constraints are met for all fields, such 51*84e33947SAndroid Build Coastguard Worker that they can be safely accessed through normal means at the location in 52*84e33947SAndroid Build Coastguard Worker memory at which they reside, when accounting for any headers, etc. 53*84e33947SAndroid Build Coastguard Worker 54*84e33947SAndroid Build Coastguard WorkerIf conditions 2 or 3 are not met, then optimized encode/decode is still possible 55*84e33947SAndroid Build Coastguard Workerafter copying the memory to a separate allocation. So in-place conversion can't 56*84e33947SAndroid Build Coastguard Workerbe done, but the only translation needed is between pointer and ChppOffset. If 57*84e33947SAndroid Build Coastguard Workerthe first condition is not met, then conversion is done using field-wise 58*84e33947SAndroid Build Coastguard Workerassignment, which allows the compiler to generate the necessary instructions to 59*84e33947SAndroid Build Coastguard Workerhandle differences in alignment and packing. 60*84e33947SAndroid Build Coastguard Worker 61*84e33947SAndroid Build Coastguard WorkerAll generated code currently assumes that it's running on a little endian CPU, 62*84e33947SAndroid Build Coastguard Workeras the wire format requires little endian byte order. 63*84e33947SAndroid Build Coastguard Worker 64*84e33947SAndroid Build Coastguard WorkerTODO: The script currently only generates code for the pessimistic case, where 65*84e33947SAndroid Build Coastguard Workernone of the constraints are met. By generating code that checks sizeof/offsetof 66*84e33947SAndroid Build Coastguard Workeron all fields and placing the optimized path in an if/else condition, the 67*84e33947SAndroid Build Coastguard Workercompiler can evaluate condition 1 and prune away code for the less-optimal path. 68*84e33947SAndroid Build Coastguard Worker 69*84e33947SAndroid Build Coastguard Worker## Annotations 70*84e33947SAndroid Build Coastguard Worker 71*84e33947SAndroid Build Coastguard WorkerAs the C API does not have enough information for the script to know how to 72*84e33947SAndroid Build Coastguard Workerhandle things like variable-length arrays (VLAs), we use the 73*84e33947SAndroid Build Coastguard Worker`chre_api_annotations.json` file to provide this detail. The supported fields 74*84e33947SAndroid Build Coastguard Worker are explained in the illustrated example below: 75*84e33947SAndroid Build Coastguard Worker 76*84e33947SAndroid Build Coastguard Worker```json 77*84e33947SAndroid Build Coastguard Worker[// A list of entries for each input file 78*84e33947SAndroid Build Coastguard Worker{ 79*84e33947SAndroid Build Coastguard Worker // Path starting at <android_root>/system/chre to the input file 80*84e33947SAndroid Build Coastguard Worker "filename": "chre_api/include/chre_api/chre/wwan.h", 81*84e33947SAndroid Build Coastguard Worker // List of #includes that also need to be parsed, e.g. because they provide 82*84e33947SAndroid Build Coastguard Worker // struct definitions that are used in the file 83*84e33947SAndroid Build Coastguard Worker "includes": [ 84*84e33947SAndroid Build Coastguard Worker "chre_api/include/chre_api/chre/common.h" 85*84e33947SAndroid Build Coastguard Worker ], 86*84e33947SAndroid Build Coastguard Worker // Which files the output header should pull in to satisfy dependencies 87*84e33947SAndroid Build Coastguard Worker "output_includes": [ 88*84e33947SAndroid Build Coastguard Worker "chpp/common/common_types.h", 89*84e33947SAndroid Build Coastguard Worker "chre_api/chre/wwan.h" 90*84e33947SAndroid Build Coastguard Worker ], 91*84e33947SAndroid Build Coastguard Worker // A list of entries providing additional information for structs/unions that 92*84e33947SAndroid Build Coastguard Worker // appear in the input 93*84e33947SAndroid Build Coastguard Worker "struct_info": [ 94*84e33947SAndroid Build Coastguard Worker { 95*84e33947SAndroid Build Coastguard Worker "name": "chreWwanCellInfoResult", 96*84e33947SAndroid Build Coastguard Worker // List of annotations for fields within the struct 97*84e33947SAndroid Build Coastguard Worker "annotations": [ 98*84e33947SAndroid Build Coastguard Worker // Instead of copying the input, always force setting a specific value 99*84e33947SAndroid Build Coastguard Worker // for a field. The value is whatever should appear in the code for the 100*84e33947SAndroid Build Coastguard Worker // assignment statement, or the value to memset it to for an array type. 101*84e33947SAndroid Build Coastguard Worker { 102*84e33947SAndroid Build Coastguard Worker // Which field within the struct this annotation applies to 103*84e33947SAndroid Build Coastguard Worker "field": "version", 104*84e33947SAndroid Build Coastguard Worker // The type of annotation we're supplying 105*84e33947SAndroid Build Coastguard Worker "annotation": "fixed_value", 106*84e33947SAndroid Build Coastguard Worker // Additional information is dependent upon the annotation type 107*84e33947SAndroid Build Coastguard Worker "value": "CHRE_WWAN_CELL_INFO_RESULT_VERSION" 108*84e33947SAndroid Build Coastguard Worker }, 109*84e33947SAndroid Build Coastguard Worker // Since the 'cookie' field here is a void*, we're rewriting to a 110*84e33947SAndroid Build Coastguard Worker // uint32_t to keep the same structure size + field offsets (on 32-bit 111*84e33947SAndroid Build Coastguard Worker // architectures) - in practice we'll also force the value to 0 112*84e33947SAndroid Build Coastguard Worker { 113*84e33947SAndroid Build Coastguard Worker "field": "cookie", 114*84e33947SAndroid Build Coastguard Worker "annotation": "rewrite_type", 115*84e33947SAndroid Build Coastguard Worker "type_override": "uint32_t" 116*84e33947SAndroid Build Coastguard Worker }, 117*84e33947SAndroid Build Coastguard Worker // Indicates a variable length array field, with the number of elements 118*84e33947SAndroid Build Coastguard Worker // given by another field in the same structure called cellInfoCount 119*84e33947SAndroid Build Coastguard Worker { 120*84e33947SAndroid Build Coastguard Worker "field": "cells", 121*84e33947SAndroid Build Coastguard Worker "annotation": "var_len_array", 122*84e33947SAndroid Build Coastguard Worker "length_field": "cellInfoCount" 123*84e33947SAndroid Build Coastguard Worker } 124*84e33947SAndroid Build Coastguard Worker ] 125*84e33947SAndroid Build Coastguard Worker }, 126*84e33947SAndroid Build Coastguard Worker { 127*84e33947SAndroid Build Coastguard Worker "name": "chreWwanCellInfo", 128*84e33947SAndroid Build Coastguard Worker "annotations": [ 129*84e33947SAndroid Build Coastguard Worker // In this case, we have a union field, where only one of the members is 130*84e33947SAndroid Build Coastguard Worker // used, according to the provided mapping on the adjacent discriminator 131*84e33947SAndroid Build Coastguard Worker // field 132*84e33947SAndroid Build Coastguard Worker { 133*84e33947SAndroid Build Coastguard Worker "field": "CellInfo", 134*84e33947SAndroid Build Coastguard Worker "annotation": "union_variant", 135*84e33947SAndroid Build Coastguard Worker "discriminator": "cellInfoType", 136*84e33947SAndroid Build Coastguard Worker "mapping": [ 137*84e33947SAndroid Build Coastguard Worker ["CHRE_WWAN_CELL_INFO_TYPE_GSM", "gsm"], 138*84e33947SAndroid Build Coastguard Worker ["CHRE_WWAN_CELL_INFO_TYPE_CDMA", "cdma"], 139*84e33947SAndroid Build Coastguard Worker ["CHRE_WWAN_CELL_INFO_TYPE_LTE", "lte"], 140*84e33947SAndroid Build Coastguard Worker ["CHRE_WWAN_CELL_INFO_TYPE_WCDMA", "wcdma"], 141*84e33947SAndroid Build Coastguard Worker ["CHRE_WWAN_CELL_INFO_TYPE_TD_SCDMA", "tdscdma"], 142*84e33947SAndroid Build Coastguard Worker ["CHRE_WWAN_CELL_INFO_TYPE_NR", "nr"] 143*84e33947SAndroid Build Coastguard Worker ] 144*84e33947SAndroid Build Coastguard Worker } 145*84e33947SAndroid Build Coastguard Worker ] 146*84e33947SAndroid Build Coastguard Worker } 147*84e33947SAndroid Build Coastguard Worker ], 148*84e33947SAndroid Build Coastguard Worker // The list of top-level structures appearing in the input that we should 149*84e33947SAndroid Build Coastguard Worker // create conversion routines for 150*84e33947SAndroid Build Coastguard Worker "root_structs": [ 151*84e33947SAndroid Build Coastguard Worker "chreWwanCellInfoResult" 152*84e33947SAndroid Build Coastguard Worker ] 153*84e33947SAndroid Build Coastguard Worker}] 154*84e33947SAndroid Build Coastguard Worker``` 155*84e33947SAndroid Build Coastguard Worker 156*84e33947SAndroid Build Coastguard Worker## Requirements 157*84e33947SAndroid Build Coastguard Worker 158*84e33947SAndroid Build Coastguard WorkerTested with Python 3.7, but most versions of Python 3 should work. 159*84e33947SAndroid Build Coastguard Worker 160*84e33947SAndroid Build Coastguard WorkerRequires pyclibrary - see requirements.txt. 161