blob: cab6fcbc7bce4d9381332600e5dd54d9fa8d46b8 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define ADK_INTERNAL
#include "fwk.h"
#include "LEDs.h"
#include "Audio.h"
#include "dbg.h"
#include "coop.h"
#include "BT.h"
#include "HCI.h"
#include "btL2CAP.h"
#include "btRFCOMM.h"
#include "btSDP.h"
#include "btA2DP.h"
#include "I2C.h"
#include "hygro.h"
#include "baro.h"
#include "capsense.h"
#include "als.h"
#include "accel.h"
#include "hygro.h"
#include "capsense.h"
#include "als.h"
#include "accel.h"
#include "mag.h"
#include "f_ff.h"
#include "simpleOgg.h"
#include "RTC.h"
#include "sgBuf.h"
void eliza(void);
#include "usbh.h"
#include "ADK.h"
static adkBtConnectionRequestF bt_crF = 0;
static adkBtLinkKeyRequestF bt_krF = 0;
static adkBtLinkKeyCreatedF bt_kcF = 0;
static adkBtPinRequestF bt_prF = 0;
static adkBtDiscoveryResultF bt_drF = 0;
static adkBtSspDisplayF bt_pdF = 0;
static FATFS fs;
static char btLinkKeyRequest(void* userData, const uint8_t* mac, uint8_t* buf){
if(bt_krF) return bt_krF(mac, buf);
dbgPrintf("BT Link key request from %02x:%02x:%02x:%02x:%02x:%02x -> denied due to lack of handler", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
return 0;
}
static uint8_t btPinRequestF(void* userData, const uint8_t* mac, uint8_t* buf){ //fill buff with PIN code, return num bytes used (16 max) return 0 to decline
if(bt_prF) return bt_prF(mac, buf);
dbgPrintf("BT PIN request from %02x:%02x:%02x:%02x:%02x:%02x -> '0000' due to lack of handler", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
buf[0] = buf[1] = buf[2] = buf[3] = '0';
return 4;
}
static void btLinkKeyCreated(void* userData, const uint8_t* mac, const uint8_t* buf){
if(bt_kcF) bt_kcF(mac, buf);
}
static char btConnReqF(void* userData, const uint8_t* mac, uint32_t devClass, uint8_t linkType){ //return 1 to accept
if(bt_crF) return bt_crF(mac, devClass, linkType);
dbgPrintf("BT connection request: %s connection from %02x:%02x:%02x:%02x:%02x:%02x (class %06X) -> accepted due to lack of handler\n", linkType ? "ACL" : "SCO", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0], devClass);
return 1;
}
static void btConnStartF(void* userData, uint16_t conn, const uint8_t* mac, uint8_t linkType, uint8_t encrMode){
dbgPrintf("BT %s connection up with handle %d to %02x:%02x:%02x:%02x:%02x:%02x encryption type %d\n",
linkType ? "ACL" : "SCO", conn, mac[5], mac[4], mac[3], mac[2], mac[1], mac[0], encrMode);
l2capAclLinkUp(conn);
}
static void btConnEndF(void* userData, uint16_t conn, uint8_t reason){
dbgPrintf("BT connection with handle %d down for reason %d\n", conn, reason);
l2capAclLinkDown(conn);
}
static void btAclDataRxF(void* userData, uint16_t conn, char first, uint8_t bcastType, const uint8_t* data, uint16_t sz){
l2capAclLinkDataRx(conn, first, data, sz);
}
static void btSspShowF(void* userData, const uint8_t* mac, uint32_t val){
if(val == BT_SSP_DONE_VAL) val = ADK_BT_SSP_DONE_VAL;
if(bt_pdF) bt_pdF(mac, val);
}
static char btVerboseScanCbkF(void* userData, BtDiscoveryResult* dr){
if(bt_drF) return bt_drF(dr->mac, dr->PSRM, dr->PSPM, dr->PSM, dr->co, dr->dc);
dbgPrintf("BT: no callback for scan makes the scan useless, no?");
return 0;
}
void ADK_adkInit(void){
//board init
fwkInit();
coopInit();
ledsInit();
i2cInit(1, 400000);
rtcInit();
rtcSet(2012, 3, 28, 19, 8, 50);
audioInit();
usbh_init();
//bt init
static const BtFuncs myBtFuncs = {NULL, btVerboseScanCbkF, btConnReqF, btConnStartF, btConnEndF, btPinRequestF, btLinkKeyRequest, btLinkKeyCreated, btAclDataRxF, btSspShowF};
btInit(&myBtFuncs); //BT UART & HCI driver
btSdpRegisterL2capService(); //SDP daemon
btRfcommRegisterL2capService(); //RFCOMM framework
eliza(); //easter egg
btA2dpRegister(); //A2DP profile
uint8_t mac[BT_MAC_SIZE];
if(btLocalMac(mac)) dbgPrintf("BT MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
//i2c devices init
if(!hygroInit()) dbgPrintf("ADK i2c init failure: hygrometer\n");
if(!baroInit()) dbgPrintf("ADK i2c init failure: barometer\n");
if(!capSenseInit()) dbgPrintf("ADK i2c init failure: capsense\n");
if(!alsInit()) dbgPrintf("ADK i2c init failure: ALS\n");
if(!accelInit()) dbgPrintf("ADK i2c init failure: accelerometer\n");
if(!magInit()) dbgPrintf("ADK i2c init failure: magnetometer\n");
}
void ADK_adkEventProcess(void){
coopYield();
}
void ADK_getUniqueId(uint32_t* ID){
cpuGetUniqId(ID);
}
uint64_t ADK_getUptime(void){ //in ms
return fwkGetUptime();
}
void ADK_adkSetPutchar(adkPutcharF f){
dbgSetPutchar(f);
}
void ADK_ledWrite(uint8_t led_id, uint8_t r, uint8_t g, uint8_t b){
ledWrite(led_id, r, g, b);
}
void ADK_ledDrawIcon(uint8_t offset, uint8_t r, uint8_t g, uint8_t b){
ledDrawIcon(offset, r, g, b);
}
void ADK_ledDrawLetter(char letter, uint8_t val, uint8_t r, uint8_t g, uint8_t b){
ledDrawLetter(letter, val, r, g, b);
}
void ADK_ledUpdate(void){
ledUpdate();
}
void ADK_ledDbgState(char on){
ledDbgState(on);
}
void ADK_audioOn(int source, uint32_t samplerate){
audioOn(source, samplerate);
}
void ADK_audioOff(int source){
audioOff(source);
}
void ADK_audioAddBuffer(int source, const uint16_t* samples, uint32_t numSamples){
audioAddBuffer(source, samples, numSamples);
}
int ADK_audioTryAddBuffer(int source, const uint16_t* samples, uint32_t numSamples){
return audioTryAddBuffer(source, samples, numSamples);
}
void ADK_btEnable(adkBtConnectionRequestF crF, adkBtLinkKeyRequestF krF, adkBtLinkKeyCreatedF kcF, adkBtPinRequestF prF, adkBtDiscoveryResultF drF){
bt_crF = crF;
bt_krF = krF;
bt_kcF = kcF;
bt_prF = prF;
bt_drF = drF;
}
void ADK_btSetSspCallback(adkBtSspDisplayF pdF){
bt_pdF = pdF;
}
char ADK_btSetLocalName(const char* name){
return btSetLocalName(name);
}
char ADK_btGetRemoteName(const uint8_t* mac, uint8_t PSRM, uint8_t PSM, uint16_t co, char* nameBuf){
return btGetRemoteName(mac, PSRM, PSM, co, nameBuf);
}
void ADK_btScan(void){
btScan();
}
char ADK_btDiscoverable(char on){
return btDiscoverable(on);
}
char ADK_btConnectable(char on){
return btConnectable(on);
}
char ADK_btSetDeviceClass(uint32_t cls){
return btSetDeviceClass(cls);
}
char ADK_hygroRead(int32_t *temp, int32_t *humidity){
return hygroRead(temp, humidity);
}
void ADK_baroRead(uint8_t oss, long *kPa, long* decicelcius){
return baroRead(oss, kPa, decicelcius);
}
uint8_t ADK_capSenseSlider(void){
return capSenseSlider();
}
uint16_t ADK_capSenseButtons(void){
return capSenseButtons();
}
uint16_t ADK_capSenseIcons(void){
return capSenseIcons();
}
void ADK_capSenseDump(void){
return capSenseDump();
}
void ADK_alsRead(uint16_t* prox, uint16_t* clear, uint16_t* R, uint16_t* G, uint16_t* B, uint16_t* IR, uint16_t* temp){
return alsRead(prox, clear, R, G, B, IR, temp);
}
void ADK_accelRead(int16_t* x, int16_t* y, int16_t* z){
accelRead(x, y, z);
}
void ADK_magRead(int16_t* x, int16_t* y, int16_t* z){
magRead(x, y, z);
}
void ADK_playOgg(const char* path){
playOgg(path);
}
void ADK_playOggBackground(const char* path, char *complete, char *doAbort) {
playOggBackground(path, complete, doAbort);
}
void ADK_setVolume(uint8_t vol){
setVolume(vol);
}
uint8_t ADK_getVolume(void){
return getVolume();
}
void ADK_rtcGet(uint16_t* yearP, uint8_t* monthP, uint8_t* dayP, uint8_t* hourP, uint8_t* minuteP, uint8_t* secondP){
rtcGet(yearP, monthP, dayP, hourP, minuteP, secondP);
}
void ADK_rtcSet(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second){
rtcSet(year, month, day, hour, minute, second);
}
char ADK_fatfsMount(void){ // Mount/Unmount a logical drive
return f_mount (0, &fs);
}
char ADK_fatfsOpen(struct FatFile** fPP, const char* path, uint8_t mode){ // Open or create a file
FIL f;
FIL* fP;
char ret;
uint8_t flg = 0;
if(mode & FATFS_READ) flg |= FA_READ;
if(mode & FATFS_WRITE) flg |= FA_WRITE;
if(mode & FATFS_CREATE) flg |= FA_CREATE_NEW | FA_OPEN_ALWAYS;
if(mode & FATFS_TRUNCATE) flg |= FA_CREATE_ALWAYS | FA_OPEN_ALWAYS;
ret = f_open(&f, path, flg);
if(ret != FR_OK) return ret;
fP = (FIL*)malloc(sizeof(FIL));
if(!fP){
f_close(&f);
return -1;
}
*fP = f;
*fPP = (struct FatFile*)fP;
return FR_OK;
}
char ADK_fatfsRead(struct FatFile* f, void* buf, uint32_t num, uint32_t* numDone){ // Read data from a file
return f_read((FIL*)f, buf, num, numDone);
}
char ADK_fatfsWrite(struct FatFile* f, void* buf, uint32_t num, uint32_t* numDone){ // Write data to a file
return f_write((FIL*)f, buf, num, numDone);
}
char ADK_fatfsSeek(struct FatFile* f_, uint8_t whence, int32_t ofst){ // Move file pointer of a file object
FIL* f = (FIL*)f_;
uint32_t pos;
pos = f->fptr;
switch(pos){
case FATFS_START: pos = ofst; break;
case FATFS_CUR: pos += ofst; break;
case FATFS_END: pos = f->fsize + ofst; break;
default: return -1;
}
return f_lseek(f, pos);
}
char ADK_fatfsClose(struct FatFile* f){ // Close an open file object
char ret;
ret = f_close((FIL*)f);
free(f);
return ret;
}
char ADK_fatfsTruncate(struct FatFile* f){ // Truncate file
return f_truncate((FIL*)f);
}
char ADK_fatfsSync(struct FatFile* f){ // Flush cached data of a writing file
return f_sync((FIL*)f);
}
char ADK_fatfsOpenDir(struct FatDir** dPP, const char* path){ // Open an existing directory
DIR d;
DIR* dP;
char ret;
ret = f_opendir(&d, path);
if(ret != FR_OK) return ret;
dP = (DIR*)malloc(sizeof(DIR));
if(!dP) return -1;
*dP = d;
*dPP = (struct FatDir*)dP;
return FR_OK;
}
static void fatfsfileInfoToFileInfo(FILINFO* fat, FatFileInfo* fatfs, char before){
if(before){
fat->lfname = fatfs->longName;
fat->lfsize = fatfs->nameSz;
}
else{
int i;
fatfs->longName = fat->lfname;
fatfs->nameSz = fat->lfsize;
fatfs->fsize = fat->fsize;
fatfs->attrib = fat->fattrib;
for(i = 0 ;i < 13; i++) fatfs->name[i] = fat->fname[i];
}
}
char ADK_fatfsReadDir(struct FatDir* d, FatFileInfo* i){ // Read a directory item
FILINFO fi;
char ret;
fatfsfileInfoToFileInfo(&fi, i, 1);
ret = f_readdir((DIR*)d, &fi);
if(ret == FR_OK) fatfsfileInfoToFileInfo(&fi, i, 0);
return ret;
}
char ADK_fatfsCloseDir(struct FatDir* d){ // Close a directory
free(d);
}
char ADK_fatfsStat(const char* path, FatFileInfo* i){ // Get file status
FILINFO fi;
char ret;
fatfsfileInfoToFileInfo(&fi, i, 1);
ret = f_stat(path, &fi);
fatfsfileInfoToFileInfo(&fi, i, 0);
return ret;
}
char ADK_fatfsGetFree(const char* path, uint64_t* freeSize){ // Get number of free space on the drive
char ret;
DWORD clus;
FATFS* fsP = &fs;
ret = f_getfree("/", &clus, &fsP);
if(freeSize) *freeSize = ((uint64_t)clus * (uint64_t)fs.csize) << 9;
return ret;
}
char ADK_fatfsUnlink(const char* path){ // Delete an existing file or directory
return f_unlink(path);
}
char ADK_fatfsMkdir(const char* path){ // Create a new directory
return f_mkdir(path);
}
char ADK_fatfsChmod(const char* path, uint8_t val, uint8_t mask){ // Change attributes of the file/dir
return f_chmod(path, val, mask);
}
char ADK_fatfsRename(const char* path, const char* newPath){ // Rename/Move a file or directory
return f_rename(path, newPath);
}
char ADK_fatfsMkfs(void){ // Create a file system on the drive
return f_mkfs(0, 0, 0);
}
void ADK_l2capServiceTx(uint16_t conn, uint16_t remChan, const uint8_t* data, uint32_t size){ //send data over L2CAP
sg_buf* buf = sg_alloc();
if(!buf) return;
if(sg_add_back(buf, data, size, SG_FLAG_MAKE_A_COPY)) l2capServiceTx(conn, remChan, buf);
else sg_free(buf);
}
void ADK_l2capServiceCloseConn(uint16_t conn, uint16_t chan){
l2capServiceCloseConn(conn, chan);
}
char ADK_l2capServiceRegister(uint16_t PSM, const L2capService* svcData){
return l2capServiceRegister(PSM, svcData);
}
char ADK_l2capServiceUnregister(uint16_t PSM){
return l2capServiceUnregister(PSM);
}
void ADK_btSdpServiceDescriptorAdd(const uint8_t* descriptor, uint16_t descrLen){
btSdpServiceDescriptorAdd(descriptor, descrLen);
}
void ADK_btSdpServiceDescriptorDel(const uint8_t* descriptor){
btSdpServiceDescriptorDel(descriptor);
}
void ADK_btRfcommRegisterPort(uint8_t dlci, BtRfcommPortOpenF oF, BtRfcommPortCloseF cF, BtRfcommPortRxF rF){
btRfcommRegisterPort(dlci, oF, cF, rF);
}
void ADK_btRfcommPortTx(void* port, uint8_t dlci, const uint8_t* data, uint16_t size){
btRfcommPortTx(port, dlci, data, size);
}
uint8_t ADK_btRfcommReserveDlci(uint8_t preference){
return btRfcommReserveDlci(preference);
}
void ADK_btRfcommReleaseDlci(uint8_t dlci){
btRfcommReleaseDlci(dlci);
}
// USB
void ADK_usbStart()
{
usbh_start();
}
void ADK_usbSetAccessoryStringVendor(const char *str)
{
usbh_set_accessory_string_vendor(str);
}
void ADK_usbSetAccessoryStringName(const char *str)
{
usbh_set_accessory_string_name(str);
}
void ADK_usbSetAccessoryStringLongname(const char *str)
{
usbh_set_accessory_string_longname(str);
}
void ADK_usbSetAccessoryStringVersion(const char *str)
{
usbh_set_accessory_string_version(str);
}
void ADK_usbSetAccessoryStringUrl(const char *str)
{
usbh_set_accessory_string_url(str);
}
void ADK_usbSetAccessoryStringSerial(const char *str)
{
usbh_set_accessory_string_serial(str);
}
int ADK_accessoryConnected()
{
return usbh_accessory_connected();
}
int ADK_accessorySend(const void *buf, unsigned int len)
{
return accessory_send(buf, len);
}
int ADK_accessoryReceive(void *buf, unsigned int len)
{
return accessory_receive(buf, len);
}
void logHardFault(unsigned long* auto_pushed, unsigned long* self_pushed); //must be global....
void logHardFault(unsigned long* auto_pushed, unsigned long* self_pushed)
{
unsigned long r[16], sr;
int i;
for(i = 0; i < 4; i++) r[i] = auto_pushed[i];
r[12] = auto_pushed[4];
r[13] = ((unsigned long)auto_pushed) - 32;
r[14] = auto_pushed[5];
r[15] = auto_pushed[6];
sr = auto_pushed[7];
for(i = 4; i < 11; i++) r[i] = self_pushed[i - 4];
dbgPrintf ("\n\n[Cortex-M3 HARD FAULT]\n");
for(i = 0 ;i < 16; i++) dbgPrintf ("R%2d = 0x%08X\n", i, r[i]);
dbgPrintf ("SR = 0x%08X\n", sr);
while (1);
}
void __attribute__((naked)) HardFault_Handler(){
asm(
"tst lr, #4 \n\t"
"ite eq \n\t"
"mrseq r0, msp \n\t"
"mrsne r0, psp \n\t"
"push {r4-r11} \n\t"
"mov r1, sp \n\t"
"B logHardFault \n\t"
);
}