⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cbus.c

📁 NOKIA手机开发包
💻 C
字号:
/*  G N O K I I  A Linux/Unix toolset and driver for Nokia mobile phones.  This file is part of gnokii.  Gnokii is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.  Gnokii is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with gnokii; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  Copyright (C) 2001 Pavel Machek <pavel@ucw.cz>  Copyright (C) 2001, 2002, 2003 Ladislav Michl <ladis@linux-mips.org> *//* System header files */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>/* Various header files */#include "config.h"#include "compat.h"#include "misc.h"#include "gnokii-internal.h"#include "device.h"#include "links/utils.h"#include "links/cbus.h"static void cbus_wait_for_idle(int timeout, struct gn_statemachine *state){	int n, prev;	device_nreceived(&n, state);	do {		prev = n;		usleep(timeout);		if (device_nreceived(&n, state) != GN_ERR_NONE) break;	} while (n != prev);}static gn_error cbus_write(unsigned char *d, int len, struct gn_statemachine *state){	int res;	cbus_wait_for_idle(300, state);	while (len) {		res = device_write(d, len, state);		if (res == -1) {			if (errno != EAGAIN) {				dprintf("I/O error : %m?!\n");				return GN_ERR_FAILED;			}		} else {			d += res;			len -= res;		}	}	device_flush(state);	return GN_ERR_NONE;}static gn_error cbus_wakeup1(struct gn_statemachine *state){	int i;	unsigned char p[] = {0x38, 0x19, 0xa6, 0x70, 0x00, 0x00, 0x00};	for (i = 0; i < 6; i++)		p[6] ^= p[i];	return cbus_write(p, sizeof(p), state);}static gn_error cbus_wakeup2(struct gn_statemachine *state){	int i;	unsigned char p[] = {0x38, 0x19, 0x90, 0x70, 0x01, 0x00, 0x44, 0x00};	for (i = 0; i < 7; i++)		p[7] ^= p[i];	return cbus_write(p, sizeof(p), state);}static gn_errorcbus_send_message(unsigned int msglen, unsigned char msgtype,		  unsigned char *msg, struct gn_statemachine *state){	unsigned char p[CBUS_MAX_FRAME_LENGTH], csum = 0;	int i, pos;	p[0] = 0x34;	p[1] = 0x19;	p[2] = msgtype;	p[3] = 0x68;	p[4] = msglen & 0xff;	p[5] = msglen >> 8;	memcpy(p+6, msg, msglen);	pos = 6+msglen;	for (i = 0; i < pos; i++)		csum ^= p[i];	p[pos++] = csum;	usleep(50000);	return cbus_write(p, pos, state);}static void dump_packet(cbus_instance *bi){	int i;	dprintf("CBUS %s ", (bi->frame_header1 == 0x19) ? "<-" : "->");	dprintf("hdr: (%02x,%02x) ", bi->frame_header1, bi->frame_header2);	dprintf("cmd: (%02x,%02x) ", bi->frame_type1, bi->frame_type2);	dprintf("len: %d\n", bi->msg_len);	if (bi->msg_len == 0)		return;	if (bi->frame_type1 == 0x3c || bi->frame_type1 == 0x3e) {		at_dprintf("        data: ", bi->msg, bi->msg_len);	} else {		dprintf("        data: ");		for (i = 0; i < bi->msg_len; i++)			dprintf("%02x ", bi->msg[i]);		dprintf("\n");	}}/* * State machine for receive handling. Called once for each character * received from the phone. * * Some machines are simply not fast enough to send 0xa5 ack byte. In that case * phone starts retransmit last frame until acked by computer (max. 3 times). * We are comparing current frame with previous one and only unique frames are * send back to statemachine. */static void cbus_rx_statemachine(unsigned char rx_byte, struct gn_statemachine *state){	cbus_instance *bi = CBUSINST(state);		if (bi->state != CBUS_RX_CSum) bi->csum ^= rx_byte;	switch (bi->state) {	case CBUS_RX_Header:		switch (rx_byte) {		case 0x38:		case 0x34:			if (bi->prev_rx_byte == 0x19)				bi->state = CBUS_RX_FrameType1;			break;		case 0x19:			if ((bi->prev_rx_byte == 0x38) || (bi->prev_rx_byte == 0x34))				bi->state = CBUS_RX_FrameType1;			break;		default:			dprintf("CBUS: discarding (%02x)\n", rx_byte);			break;		}		if (bi->state != CBUS_RX_Header) {			bi->frame_header1 = bi->prev_rx_byte;			bi->frame_header2 = rx_byte;			bi->csum = bi->prev_rx_byte ^ rx_byte;			bi->msg_pos = 0;		}		break;	case CBUS_RX_FrameType1:		bi->unique = bi->frame_type1 != rx_byte;		bi->frame_type1 = rx_byte;		bi->state = CBUS_RX_FrameType2;		break;	case CBUS_RX_FrameType2:		bi->unique |= bi->frame_type1 != rx_byte;		bi->frame_type2 = rx_byte;		bi->state = CBUS_RX_LengthLB;		break;	/* message length - low byte */	case CBUS_RX_LengthLB:		bi->msg_len = rx_byte;		bi->state = CBUS_RX_LengthHB;		break;	/* message length - high byte */	case CBUS_RX_LengthHB:		bi->msg_len = bi->msg_len | rx_byte << 8;		/* there are also empty messages */		if (bi->msg_len == 0)			bi->state = CBUS_RX_CSum;		else			bi->state = CBUS_RX_Message;		break;	/* get each byte of the message body */	case CBUS_RX_Message:		bi->unique |= bi->msg[bi->msg_pos] != rx_byte;		bi->msg[bi->msg_pos++] = rx_byte;		/* avoid buffer overflow */		if (bi->msg_pos == CBUS_MAX_MSG_LENGTH) {			dprintf("CBUS: Message buffer overun - resetting\n");			bi->state = CBUS_RX_Header;			break;		}		if (bi->msg_pos == bi->msg_len) {			bi->msg[bi->msg_pos] = 0;			bi->state = CBUS_RX_CSum;		}		break;	case CBUS_RX_CSum:		/* crc error? */		if (bi->csum != rx_byte) {			dprintf("CBUS: Checksum error!\n");			bi->state = CBUS_RX_Header;			break;		}		dump_packet(bi);		/* Deal with exceptions to the rules - acks... */		if (bi->frame_header1 == 0x19) {			dprintf("CBUS: sending ack\n");			device_write("\xa5", 1, state);			device_flush(state);			if (bi->unique)				sm_incoming_function(bi->frame_type1, bi->msg,						     bi->msg_len, state);			else				dprintf("CBUS: discarding frame.\n");		}		bi->state = CBUS_RX_Ack;		break;	/* get ack */	case CBUS_RX_Ack:		if (rx_byte == 0xa5) {			if (bi->frame_header1 != 0x19) {				dprintf("CBUS: got ack\n");				sm_incoming_acknowledge(state);			}		} else			dprintf("CBUS: ack expected, got 0x%02x\n", rx_byte);		bi->state = CBUS_RX_Header; 		break;	default:		break;	}	bi->prev_rx_byte = rx_byte;}static gn_error bus_reset(struct gn_statemachine *state){	tcsendbreak(device_getfd(state), 0);	cbus_wakeup1(state);	sm_block(0, 100 ,NULL, state);	usleep(50000);	cbus_wakeup2(state);	sm_block(0, 100, NULL, state);	return GN_ERR_NONE;}static bool cbus_open_serial(char *device, struct gn_statemachine *state){	int result = device_open(device, false, false, false, GN_CT_Serial, state);	if (!result) {		perror(_("Couldn't open CBUS device"));		return false;	}	device_changespeed(9600, state);	device_setdtrrts(1, 0, state);	return true;}/*  * This is the main loop function which must be called regularly * timeout can be used to make it 'busy' or not  */static gn_error cbus_loop(struct timeval *timeout, struct gn_statemachine *state){	unsigned char buffer[255];	int count, res;	res = device_select(timeout, state);	if (res > 0) {		res = device_read(buffer, sizeof(buffer), state);		for (count = 0; count < res; count++)			cbus_rx_statemachine(buffer[count], state);	} else		return GN_ERR_TIMEOUT;	/* This traps errors from device_read */	if (res > 0)		return GN_ERR_NONE;	else		return GN_ERR_INTERNALERROR;}/* Initialise variables and start the link */gn_error cbus_initialise(struct gn_statemachine *state){	gn_error error = GN_ERR_NONE;	cbus_instance *businst;	if (!(businst = malloc(sizeof(cbus_instance))))		return GN_ERR_FAILED;	/* Fill in the link functions */	state->link.loop = &cbus_loop;	state->link.send_message = &cbus_send_message;	CBUSINST(state) = businst;	if (state->config.connection_type == GN_CT_Serial) {		if (!cbus_open_serial(state->config.port_device, state))			error = GN_ERR_FAILED;	} else {		dprintf("Device not supported by C-bus\n");		error = GN_ERR_FAILED;	}	if (error) {		dprintf("C-bus initialization failed (%d)\n", error);		free(CBUSINST(state));		CBUSINST(state) = NULL;	} else {		error = bus_reset(state);	}	return error;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -