/*---------------------------------------------------------------------------*/ static void pa_table_write(uint8_t val) { uint8_t table[8]; int i; for(i = 0; i < sizeof(table); i++) { table[i] = val; } burst_write(CC1101_PATABLE, table, 8); }
static int ec_command_lpc_3(int command, int version, const void *outdata, int outsize, void *indata, int insize) { struct ec_host_request rq; struct ec_host_response rs; const uint8_t *d; int csum = 0; int i; /* Fail if output size is too big */ if (outsize + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) return -EC_RES_REQUEST_TRUNCATED; /* Fill in request packet */ /* TODO(crosbug.com/p/23825): This should be common to all protocols */ rq.struct_version = EC_HOST_REQUEST_VERSION; rq.checksum = 0; rq.command = command; rq.command_version = version; rq.reserved = 0; rq.data_len = outsize; /* Copy data and start checksum */ burst_write((const uint8_t *)outdata, &csum, EC_LPC_ADDR_HOST_PACKET + sizeof(rq), outsize); /* Finish checksum */ for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++) csum += *d; /* Write checksum field so the entire packet sums to 0 */ rq.checksum = (uint8_t)(-csum); /* Copy header */ burst_write((const uint8_t *)&rq, NULL, EC_LPC_ADDR_HOST_PACKET, sizeof(rq)); /* Start the command */ send_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); if (wait_for_ec(EC_LPC_ADDR_HOST_CMD, 1000000)) { fprintf(stderr, "Timeout waiting for EC response\n"); return -EC_RES_ERROR; } /* Check result */ i = read_byte(EC_LPC_ADDR_HOST_DATA); if (i) { fprintf(stderr, "EC returned error result code %d\n", i); return -EECRESULT - i; } /* Read back response header and start checksum */ csum = 0; burst_read((uint8_t *)&rs, &csum, EC_LPC_ADDR_HOST_PACKET, sizeof(rs)); if (rs.struct_version != EC_HOST_RESPONSE_VERSION) { fprintf(stderr, "EC response version mismatch\n"); return -EC_RES_INVALID_RESPONSE; } if (rs.reserved) { fprintf(stderr, "EC response reserved != 0\n"); return -EC_RES_INVALID_RESPONSE; } if (rs.data_len > insize) { fprintf(stderr, "EC returned too much data\n"); return -EC_RES_RESPONSE_TOO_BIG; } /* Read back data and update checksum */ burst_read((uint8_t *)indata, &csum, EC_LPC_ADDR_HOST_PACKET + sizeof(rs), rs.data_len); /* Verify checksum */ if ((uint8_t)csum) { fprintf(stderr, "EC response has invalid checksum\n"); return -EC_RES_INVALID_CHECKSUM; } /* Return actual amount of data received */ return rs.data_len; }
/*---------------------------------------------------------------------------*/ static void write_txfifo(uint8_t *data, uint8_t len) { #define BURST_BIT 0x40 uint8_t status; int i; #define CC1101_STATUS_STATE_MASK 0x70 #define CC1101_STATUS_STATE_TXFIFO_UNDERFLOW 0x70 /* ensure FIFO is empty before tx */ strobe(CC1101_SIDLE); strobe(CC1101_SFTX); is_transmitting = 1; LOCK_SPI(); burst_write(CC1101_TXFIFO, &len, 1); #define FIRST_TX 60 /* Must not be 62 or above! */ i = MIN(len, FIRST_TX); burst_write(CC1101_TXFIFO, data, i); strobe(CC1101_STX); if(len > i) { cc1101_arch_enable(); cc1101_arch_write_command(CC1101_TXFIFO | BURST_BIT); for(; i < len; i++) { status = cc1101_arch_write_data(data[i]); if((status & CC1101_STATUS_STATE_MASK) == CC1101_STATUS_STATE_TXFIFO_UNDERFLOW) { cc1101_arch_disable(); /* TX FIFO underflow, acknowledge it with an SFTX (else the CC1101 becomes completely unresponsive) followed by an SRX, and break the transmission. */ strobe(CC1101_SFTX); strobe(CC1101_SRX); break; #define MIN_TXFIFO_AVAILABLE 2 } else if((status & 0x0f) < MIN_TXFIFO_AVAILABLE) { cc1101_arch_disable(); BUSYWAIT_UNTIL(txbytes() < 60 || (txbytes() & 0x80) != 0, RTIMER_SECOND / 10); if(txbytes() & 0x80) { /* printf("TxUF2\n");*/ /* TX FIFO underflow. */ strobe(CC1101_SFTX); strobe(CC1101_SRX); break; } /* If there are more bytes to write, we should issue another TXFIFO write command. */ if(i < len - 1) { cc1101_arch_enable(); cc1101_arch_write_command(CC1101_TXFIFO | BURST_BIT); } } } cc1101_arch_disable(); } RELEASE_SPI(); is_transmitting = 0; }
static int ec_command_lpc(int command, int version, const void *outdata, int outsize, void *indata, int insize) { struct ec_lpc_host_args args; int csum; int i; /* Fill in args */ args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; args.command_version = version; args.data_size = outsize; /* Initialize checksum */ csum = command + args.flags + args.command_version + args.data_size; /* Write data and update checksum */ burst_write((uint8_t *)outdata, &csum, EC_LPC_ADDR_HOST_PARAM, outsize); /* Finalize checksum and write args */ args.checksum = (uint8_t)csum; burst_write((const uint8_t *)&args, NULL, EC_LPC_ADDR_HOST_ARGS, sizeof(args)); send_byte(command, EC_LPC_ADDR_HOST_CMD); if (wait_for_ec(EC_LPC_ADDR_HOST_CMD, 1000000)) { fprintf(stderr, "Timeout waiting for EC response\n"); return -EC_RES_ERROR; } /* Check result */ i = read_byte(EC_LPC_ADDR_HOST_DATA); if (i) { fprintf(stderr, "EC returned error result code %d\n", i); return -EECRESULT - i; } /* Read back args */ burst_read((uint8_t *)&args, NULL, EC_LPC_ADDR_HOST_ARGS, sizeof(args)); /* * If EC didn't modify args flags, then somehow we sent a new-style * command to an old EC, which means it would have read its params * from the wrong place. */ if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) { fprintf(stderr, "EC protocol mismatch\n"); return -EC_RES_INVALID_RESPONSE; } if (args.data_size > insize) { fprintf(stderr, "EC returned too much data\n"); return -EC_RES_INVALID_RESPONSE; } /* Start calculating response checksum */ csum = command + args.flags + args.command_version + args.data_size; /* Read response and update checksum */ burst_read((uint8_t *)indata, &csum, EC_LPC_ADDR_HOST_PARAM, args.data_size); /* Verify checksum */ if (args.checksum != (uint8_t)csum) { fprintf(stderr, "EC response has invalid checksum\n"); return -EC_RES_INVALID_CHECKSUM; } /* Return actual amount of data received */ return args.data_size; }