?? main.c
字號:
/*
SPP master
*/
#include <cm_rfcomm.h>
#include <message.h>
#include <panic.h>
#include <pio.h>
#include <ps.h>
#include <sched.h>
#include <stream.h>
#include <timer.h>
#include <vm.h>
/* Don't enable this on chip; the application will stop running */
/* #define DEBUG_PRINT_ENABLED */
#include <print.h>
#include <stdlib.h>
#include <string.h>
#include "spp_master_service_record.h" /* Autogenerated from spp_master.sdp */
#include "../spp_common/config.h"
#include "../spp_common/invalid.h"
#include "../spp_common/lights.h"
#include "../spp_common/store.h"
#include "../spp_common/transport.h"
/* The UID of the SerialPort profile */
#define SERIAL_PORT 0x1101
/* The pin key. You probably want to change this */
static const uint16 THE_PIN[8] = { 'N', 'o', 'P', 'i', 'n', 'S', 'e', 't' };
/* Program state */
static enum { starting, inquiring, pairing, connecting, active } state = starting;
static uint16 have_paired = 0;
/* Report current state of play */
#ifdef DEBUG_PRINT_ENABLED
static void status(const char *s)
{
PRINT(("State %d, far addr %lx %x %x, event %s\n", state, far_addr.lap, far_addr.nap, far_addr.uap, s));
}
#else
#define status(s) (void) 0
#endif
/* Send requests to the connection manager */
static void cm_init_req(void)
{
/* Send first message to connection manager before starting scheduler */
MAKE_MSG(CM_INIT_REQ);
MessagePut(CM, msg);
}
static void cm_open_req(void)
{
MAKE_MSG(CM_OPEN_REQ);
msg->sizeServiceRecord = sizeof(spp_master_service_record);
msg->serviceRecord = PanicNull(malloc(sizeof(spp_master_service_record)));
memcpy(msg->serviceRecord, spp_master_service_record, sizeof(spp_master_service_record));
msg->classOfDevice = 0;
MessagePut(CM, msg);
}
static void cm_write_cod(void)
{
MAKE_MSG(CM_WRITE_COD_REQ);
msg->class_of_device = CLASS_OF_DEVICE;
MessagePut(CM, msg);
}
static void cm_connect_as_master_req(void)
{
MAKE_MSG(CM_CONNECT_AS_MASTER_REQ);
config_use(&msg->use);
config_park(&msg->park);
config_sniff(&msg->sniff);
/* Look for a serial port at the far end */
msg->bd_addr = far_addr;
msg->target = SERIAL_PORT;
msg->timeout = D_SEC(60);
msg->max_framesize = MAX_FRAMESIZE;
MessagePut(CM, msg);
}
static void cm_cancel_req(void)
{
MAKE_MSG(CM_CANCEL_REQ);
MessagePut(CM, msg);
}
static void cm_disconnect_req(void)
{
MAKE_MSG(CM_DISCONNECT_REQ);
msg->link_type = RfcommConnection;
msg->addr = far_addr;
MessagePut(CM, msg);
}
static void cm_inquiry_req(void)
{
MAKE_MSG(CM_INQUIRY_REQ);
msg->max_responses = 8;
msg->inq_timeout = D_SEC(60);
msg->class_of_device = CLASS_OF_DEVICE;
msg->remote_name_request_enabled = 0;
MessagePut(CM, msg);
}
static void cm_pair_req(void)
{
MAKE_MSG(CM_PAIR_REQ);
msg->role = CmMaster;
msg->timeout = D_SEC(10);
msg->authentication = 1;
msg->bd_addr = far_addr;
MessagePut(CM, msg);
}
static void cm_add_sm_device_req(const uint8 *link_key)
{
MAKE_MSG(CM_ADD_SM_DEVICE_REQ);
msg->addr = far_addr;
memcpy(msg->link_key, link_key, SIZE_LINK_KEY);
msg->trust = 1;
MessagePut(CM, msg);
}
static void cm_pin_code_res(const BD_ADDR_T *addr)
{
MAKE_MSG(CM_PIN_CODE_RES);
bool accept = !know_far_addr() || (far_addr.nap == addr->nap && far_addr.lap == addr->lap && far_addr.uap == addr->uap);
msg->addr = *addr;
msg->pin_length = accept ? sizeof(THE_PIN) < 8 ? sizeof(THE_PIN) : 8 : 0;
memcpy(msg->pin, THE_PIN, msg->pin_length);
MessagePut(CM, msg);
}
static void cm_link_key_res(const BD_ADDR_T *other)
{
MAKE_MSG(CM_LINK_KEY_RES);
msg->accept = far_addr.lap == other->lap
&& far_addr.nap == other->nap
&& far_addr.uap == other->uap
&& read_link_key(msg->key_val);
msg->addr = *other;
if(!msg->accept) memset(msg->key_val, 0, SIZE_LINK_KEY);
MessagePut(CM, msg);
}
/* Keep a list of addresses we've tried before without success */
enum { FAILED_SIZE = 8 };
static BD_ADDR_T failed_addr[FAILED_SIZE];
static uint16 tried_and_failed(const BD_ADDR_T *addr)
{
static uint16 failed_next;
uint16 i;
for(i = 0; i < FAILED_SIZE; ++i)
if(failed_addr[i].lap == addr->lap
&& failed_addr[i].nap == addr->nap
&& failed_addr[i].uap == addr->uap)
return 1;
failed_addr[failed_next] = *addr;
++failed_next;
if(failed_next == FAILED_SIZE) failed_next = 0;
return 0;
}
/* Handle incoming messages from the connection manager */
static void forward(void)
{
if(!know_far_addr())
{
/* If we don't know who we're meant to be talking to, start looking. */
status("Inquiring");
cm_inquiry_req();
state = inquiring;
lights_inquiring();
}
else if(!have_paired)
{
/* If we know who is at the far end, but we're not paired, do that now. */
status("Pairing");
cm_pair_req();
state = pairing;
lights_pairing();
}
else
{
/* If we get here, we know who's at the far end and we've paired with them. Connect. */
status("Connecting");
cm_connect_as_master_req();
state = connecting;
lights_connecting();
}
}
DECLARE_TASK(1)
{
MessageType type ;
void * msg = MessageGet(1,&type) ;
if (msg)
{
switch (type)
{
case CM_INIT_CFM:
status("init_cfm");
cm_open_req();
break;
case CM_OPEN_CFM:
status("open_cfm");
cm_write_cod();
forward();
break;
case CM_SERVICE_REGISTER_CFM:
/* Don't care */
break;
case CM_CONNECT_CFM:
{
CM_CONNECT_CFM_T *prim = (CM_CONNECT_CFM_T *) msg;
connect_status_t result = prim->status;
if(result == CmConnectComplete)
{
Source rfcomm_source = prim->source;
Sink rfcomm_sink = prim->sink;
status("connect_cfm complete");
PanicFalse(TransportConnect(rfcomm_source, rfcomm_sink));
state = active;
lights_connected();
}
else
{
status("connect_cfm failure");
forward();
}
}
break;
case CM_CONNECT_STATUS_IND:
/* Disconnected. Start again. */
status("connect_status_ind");
forward();
break;
case CM_INQUIRY_RESULT_IND:
{
CM_INQUIRY_RESULT_IND_T *prim = (CM_INQUIRY_RESULT_IND_T *) msg;
status("inquiry_result_ind");
if(!tried_and_failed(&prim->inq_result.bd_addr))
{
far_addr = prim->inq_result.bd_addr;
cm_cancel_req();
/* Will issue next request after INQUIRY_COMPLETE_CFM */
}
}
break;
case CM_INQUIRY_COMPLETE_CFM:
{
status("inquiry_complete_cfm");
forward();
}
break;
case CM_PAIR_CFM:
{
CM_PAIR_CFM_T *prim = (CM_PAIR_CFM_T *) msg;
status("pair_cfm");
switch(prim->status)
{
case CmPairingNotFinished:
/* We get the link key here */
write_link_key(prim->link_key);
break;
case CmPairingComplete:
/* But pairing isn't complete until this message arrives */
write_far_addr();
have_paired = 1;
forward();
break;
case CmPairingTimeout:
case CmPairingCancelled:
case CmPairingFail:
/* Didn't work */
have_paired = 0;
clear_far_addr();
forward();
break;
}
}
break;
case CM_PIN_CODE_REQ:
status("cm_pin_code_req");
cm_pin_code_res(&((CM_PIN_CODE_REQ_T *) msg)->addr);
break;
case CM_LINK_KEY_REQ:
status("cm_link_key_req");
cm_link_key_res(&((CM_LINK_KEY_REQ_T *) msg)->addr);
break;
case CM_CONTROL_IND:
TransportModemStatusControl((CM_CONTROL_IND_T *)msg);
break;
case CM_ERROR_IND:
{
cm_error_t error = ((CM_ERROR_IND_T *) msg)->error;
if(error >= CmWarnLocalSniffNotEnabled || error == CmErrorCancelWhenIdle)
{
/* Ignore warnings */
break;
}
PRINT(("Error %d\n", error));
}
/*lint -fallthrough and panic */
default:
/* Unexpected message */
PRINT(("Type %d\n", type));
status("Panic");
Panic();
break;
}
MessageDestroy(msg);
}
}
static void appPioEvent(uint16 pressed)
{
if(BUTTON_DOWN(pressed))
{
have_paired = 0;
clear_far_addr();
clear_link_key();
memset(failed_addr, 0, sizeof(failed_addr));
status("button pressed");
switch(state)
{
case starting:
break;
case pairing:
case connecting:
case inquiring:
cm_cancel_req();
break;
case active:
cm_disconnect_req();
break;
}
state = starting;
}
invalid_update(pressed);
}
static const uint16 INPUT = BUTTON | INVALID;
const SchedPioEntry applicationPioEntry = { &INPUT, appPioEvent };
int main(void)
{
/* Refuse to run unless the transport has been successfully initialised */
if(TransportInit())
{
/* Tell scheduler we are using our pio entry */
SchedPioEntryChanged();
/* Enable the LEDs as outputs, other lines as inputs */
PioSetDir(LED_CONNECT|LED_POWER|BUTTON|INVALID, LED_CONNECT|LED_POWER);
#ifdef CSR_APPLICATION_HARDWARE
PioSet(BUTTON|INVALID, ~0); /* Enable VERY weak pull-ups */
PioSet(LED_CONNECT | LED_POWER, LED_CONNECT); /* only power on initially */
#else
PioSet(LED_CONNECT, 0);
#endif
invalid_update(PioGet());
read_far_addr();
if(know_far_addr())
{
uint8 link_key[SIZE_LINK_KEY];
if(read_link_key(link_key))
{
cm_add_sm_device_req(link_key);
have_paired = 1;
}
}
status("Init");
TimerInit();
cm_init_req();
Sched();
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -