unify RFCOMM frame creation

This commit is contained in:
matthias.ringwald 2009-10-17 09:40:36 +00:00
parent 332748b355
commit 8396a0038f
2 changed files with 87 additions and 73 deletions

View File

@ -1,14 +1,16 @@
/* new todo file for BTstack */
Last milestone reached: create script to build APT package for BTdeamon, Resources, and BTstack client library
Last change: added Cocoa CFRunLoop support
Last change: don't set name to empty string on error in CocoaTouch
NEXT:
- CocoaTouch User Interface Components
- Inquiry
- Alerts
- Show alert when BTstack open fails because of no BTdaemon
- Show alert when BTstack init fails because of other stack
- define delegate interface for select events
- prepare WiiMoteDemo for release
- add inquiry code
- integrate new inquiry code
- figure out why stack doesn't shut Bluetooth off when in sleep for a while
- provide test version by setting up APT repository within BTstack SVN
- instructions: http://www.saurik.com/id/7
@ -20,10 +22,10 @@ NEXT:
- commands and events
- detect and handle iPhone sleep mode
- see iPhone imnsomnia project at http://code.google.com/p/iphone-insomnia/
- can we get willGoToSleep event, should we should down?
- can we get willGoToSleep event, should we turn off Bluetooth?
- would be nice, if we could get woken up by Bluetooth data
- CocoaTouch User Interface Components
- Alerts and shutdown of Apple's stack
- Warning and shutdown of Apple's stack
- create new GPG key for gmail account and sign APT package
- non-reproducible bug: hci_state gets confused.
- BlueTool used although hci state should be on (right after quitting example/test)

View File

@ -46,51 +46,94 @@
bd_addr_t addr = {0x00,0x1c,0x4d,0x02,0x1a,0x77}; // Zeemote
// bd_addr_t addr = {0x00,0x16,0xcb,0x09,0x94,0xa9}; // sh-mac
// bd_addr_t addr = {0x00,0x0b,0x24,0x37,0xd6,0x80}; // cl800bt
// bd_addr_t addr = {0x00,0x0b,0x24,0x37,0xd6,0x80}; // smart card reader
// bd_addr_t addr = {0x00,0x80,0x25,0x07,0x2b,0x5f}; // cl800bt
#define RFCOMM_CHANNEL_ID 1
hci_con_handle_t con_handle;
uint16_t source_cid;
// used to assemble rfcomm packets
uint8_t rfcomm_out_buffer[1000];
/**
* @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
*/
void rfcomm_send_packet(uint16_t source_cid, uint8_t address, uint8_t control, uint8_t credits, uint8_t *data, uint16_t len){
uint16_t pos = 0;
uint8_t crc_fields = 3;
rfcomm_out_buffer[pos++] = address;
rfcomm_out_buffer[pos++] = control;
// length field can be 1 or 2 octets
if (len < 128){
rfcomm_out_buffer[pos++] = (len << 1)| 1; // bits 0-6
} else {
rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
rfcomm_out_buffer[pos++] = len >> 7; // bits 7-14
crc_fields++;
}
// add credits for UIH frames when PF bit is set
if (control == BT_RFCOMM_UIH_PF){
rfcomm_out_buffer[pos++] = credits;
}
// copy actual data
memcpy(&rfcomm_out_buffer[pos], data, len);
pos += len;
// UIH frames only calc FCS over address + control (5.1.1)
if ((control & 0xef) == BT_RFCOMM_UIH){
crc_fields = 2;
}
rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
bt_send_l2cap( source_cid, rfcomm_out_buffer, pos);
}
void _bt_rfcomm_send_sabm(uint16_t source_cid, uint8_t initiator, uint8_t channel)
{
uint8_t payload[4];
payload[0] = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
payload[1] = BT_RFCOMM_SABM; // control field
payload[2] = (0 << 2) | 1; // set EA bit to 1 to indicate 7 bit length field
payload[3] = crc8_calc(payload, 3); // calc fcs
bt_send_l2cap( source_cid, payload, sizeof(payload));
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
rfcomm_send_packet(source_cid, address, BT_RFCOMM_SABM, 0, NULL, 0);
}
void _bt_rfcomm_send_uih_msc_cmd(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t signals)
{
uint8_t payload[8];
// This is a command
payload[0] = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
payload[1] = BT_RFCOMM_UIH; // control field
payload[2] = 4 << 1 | 1; // len
payload[3] = BT_RFCOMM_MSC_CMD;
payload[4] = 2 << 1 | 1; // len
payload[5] = (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3); // shouldn't D = initiator = 1 ?
payload[6] = signals;
payload[7] = crc8_calc(payload, 2); // calc fcs, 3 bytes to be send...
bt_send_l2cap( source_cid, payload, sizeof(payload));
uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
uint8_t payload[4];
uint8_t pos = 0;
payload[pos++] = BT_RFCOMM_MSC_CMD;
payload[pos++] = 2 << 1 | 1; // len
payload[pos++] = (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3); // shouldn't D = initiator = 1 ?
payload[pos++] = signals;
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
}
void _bt_rfcomm_send_uih_data(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t *data, uint16_t len) {
uint8_t payload[len+4];
payload[0] = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
payload[1] = BT_RFCOMM_UIH; // control field
payload[2] = (len<<1) | 1; // len
memcpy(&payload[3], data, len);
payload[3+len] = crc8_calc(payload, 2); // calc fcs
bt_send_l2cap( source_cid, payload, sizeof(payload));
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, data, len);
}
void _bt_rfcomm_send_uih_pn_command(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint16_t max_frame_size){
uint8_t payload[10];
uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
uint8_t pos = 0;
payload[pos++] = BT_RFCOMM_PN_CMD;
payload[pos++] = 8 << 1 | 1; // len
payload[pos++] = channel << 1;
payload[pos++] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
payload[pos++] = 0; // priority
payload[pos++] = 0; // max 60 seconds ack
payload[pos++] = max_frame_size & 0xff; // max framesize low
payload[pos++] = max_frame_size >> 8; // max framesize high
payload[pos++] = 0x00; // number of retransmissions
payload[pos++] = 0x00; // unused error recovery window
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
}
void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
@ -104,36 +147,13 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
case L2CAP_DATA_PACKET:
// rfcomm: data[8] = addr
// rfcomm: data[9] = command
//
// received 1. message BT_RF_COMM_UA
if (size == 12 && packet[9] == BT_RFCOMM_UA && packet[8] == 0x03){
packet_processed++;
printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
printf("Sending UIH Parameter Negotiation Command\n");
// _bt_rfcomm_send_sabm(source_cid, 1, 1);
uint8_t payload[14];
uint8_t initiator = 1;
uint8_t channel = RFCOMM_CHANNEL_ID;
payload[0] = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
payload[1] = BT_RFCOMM_UIH; // control field
payload[2] = 10 << 1 | 1; // len
payload[3] = BT_RFCOMM_PN_CMD;
payload[4] = 8 << 1 | 1; // len
payload[5] = channel << 1;
payload[6] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
payload[7] = 0; // priority
payload[8] = 0; // max 60 seconds ack
payload[9] = 0x96; // max framesize low
payload[10] = 0x06; // max framesize high
payload[11] = 0x00; // number of retransmissions
payload[12] = 0x00; // unused error recovery window
payload[13] = crc8_calc(payload, 2 ); // calc fcs, 3 bytes to be send...
bt_send_l2cap( source_cid, payload, sizeof(payload));
_bt_rfcomm_send_uih_pn_command(source_cid, 1, RFCOMM_CHANNEL_ID, 100);
}
// received UIH Parameter Negotiation Response
@ -144,7 +164,6 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
_bt_rfcomm_send_sabm(source_cid, 1, 1);
}
// received 2. message BT_RF_COMM_UA
if (size == 12 && packet[9] == BT_RFCOMM_UA && packet[8] == ((RFCOMM_CHANNEL_ID << 3) | 3) ){
packet_processed++;
@ -160,11 +179,9 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
printf("Responding to 'I'm ready'\n");
// fine with this
uint8_t * payload = &packet[8];
payload[0] |= 2; // response
payload[3] = BT_RFCOMM_MSC_RSP;
payload[7] = crc8_calc(payload, 2);
bt_send_l2cap( source_cid, payload, 8);
//
uint8_t address = payload[0] | 2; // set response
payload[3] = BT_RFCOMM_MSC_RSP; // " "
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH_PF, 0x30, payload, 8);
msc_resp_send = 1;
}
@ -201,15 +218,10 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
}
if (send_credits_packet) {
// send 0x30 credits
uint8_t initiator = 1;
uint8_t channel = RFCOMM_CHANNEL_ID;
uint8_t payload[5];
payload[0] = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
payload[1] = BT_RFCOMM_UIH_PF; // control field
payload[2] = (0<<1) | 1; // len
payload[3] = 0x30; // credits
payload[4] = crc8_calc(payload, 2); // calc fcs
bt_send_l2cap( source_cid, payload, sizeof(payload));
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (RFCOMM_CHANNEL_ID << 3);
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH_PF, 0x30, NULL, 0);
}
if (!packet_processed){