2011-07-18 22:33:40 +02:00
/*
2011-07-23 21:32:08 +02:00
* ( c ) 2011 Siegen , Germany by Nils Faerber < nils . faerber @ kernelconcepts . de >
2011-07-18 22:33:40 +02:00
*
2011-07-30 22:45:11 +02:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
2011-07-18 22:33:40 +02:00
*/
2011-07-23 21:32:08 +02:00
2011-07-18 22:33:40 +02:00
# include <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
2011-07-19 14:13:11 +02:00
# include <unistd.h>
# include <stdlib.h>
2011-07-19 12:31:32 +02:00
# include <string.h>
# include <time.h>
2011-07-19 14:13:11 +02:00
# include <termios.h>
2011-07-23 21:32:08 +02:00
# include <ctype.h>
2011-07-18 22:33:40 +02:00
2011-07-24 17:27:28 +02:00
# include "metawatch.h"
2011-07-18 22:33:40 +02:00
# include "metawatch_protocol.h"
2011-07-19 12:31:32 +02:00
# include "crc16ccitt.h"
2011-07-24 17:27:28 +02:00
# ifdef DEBUG
const char * mw_screen_mode_names [ ] = {
" idle screen " ,
" application screen " ,
" notification screen " ,
" scroll "
} ;
const char * mw_status_string [ ] = {
" Reserved " ,
" Mode Change " ,
" Display Timeout "
} ;
# endif
2011-07-23 19:08:06 +02:00
# define MW_FRAME_DELAY 0x00
2011-08-13 13:22:22 +02:00
/* ----------------------------------------------------------------------
* Debugging helpers
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-07-19 12:31:32 +02:00
void dump_frame ( unsigned char * frame , int len )
{
2011-07-23 17:56:24 +02:00
int i ;
for ( i = 0 ; i < len ; i + + )
fprintf ( stderr , " 0x%02x " , frame [ i ] ) ;
fprintf ( stderr , " \n " ) ;
2011-07-19 12:31:32 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_send_frame ( mwdevice_t * mwdevice , unsigned char msg_type , unsigned char options , unsigned char * data , unsigned char len )
2011-07-19 12:31:32 +02:00
{
2011-07-23 17:56:24 +02:00
unsigned short crc ;
unsigned char frame [ 64 ] ;
int tlen = len + 6 ; /* payload + 6 bytes frameing */
int ret ;
memset ( frame , 0 , 64 ) ;
frame [ 0 ] = MW_SOF ;
frame [ 1 ] = len + 6 ;
frame [ 2 ] = msg_type ;
frame [ 3 ] = options ;
if ( data ! = NULL & & len > 0 )
memcpy ( frame + 4 , data , len ) ;
2011-07-19 12:31:32 +02:00
2011-07-23 17:56:24 +02:00
crc = crc16ccitt ( frame , len + 4 ) ;
* ( unsigned short * ) ( frame + len + 4 ) = crc ;
2011-07-19 12:31:32 +02:00
2011-07-23 21:32:08 +02:00
# ifdef DEBUG
2011-07-23 17:56:24 +02:00
dump_frame ( frame , tlen ) ;
2011-07-23 21:32:08 +02:00
# endif
2011-07-19 14:13:11 +02:00
2011-08-13 13:22:22 +02:00
while ( ( ( ret = write ( mwdevice - > mw_fd , frame , tlen ) ) > = 0 ) & & ( tlen > 0 ) )
2011-07-23 17:56:24 +02:00
tlen - = ret ;
2011-07-23 19:08:06 +02:00
if ( MW_FRAME_DELAY )
usleep ( MW_FRAME_DELAY ) ;
2011-07-23 17:56:24 +02:00
if ( tlen = = 0 & & ret > = 0 )
return 0 ;
else
return ret ;
2011-07-19 12:31:32 +02:00
}
2011-07-24 17:27:28 +02:00
/* ----------------------------------------------------------------------
* Host to watch commands
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-07-23 17:56:24 +02:00
2011-08-13 13:22:22 +02:00
int mw_set_rtc ( mwdevice_t * mwdevice , unsigned char clk1224 , unsigned char date_fmt )
2011-07-19 12:31:32 +02:00
{
2011-07-23 17:56:24 +02:00
time_t mtime ;
struct tm mtm ;
unsigned short year ;
unsigned char data [ 32 ] ;
mtime = time ( NULL ) ;
localtime_r ( & mtime , & mtm ) ;
year = mtm . tm_year + 1900 ;
data [ 0 ] = ( year & 0x0f00 ) > > 8 ;
data [ 1 ] = ( year & 0x00ff ) ;
data [ 2 ] = mtm . tm_mon + 1 ;
data [ 3 ] = mtm . tm_mday ;
data [ 4 ] = mtm . tm_wday ;
data [ 5 ] = mtm . tm_hour ;
data [ 6 ] = mtm . tm_min ;
data [ 7 ] = mtm . tm_sec ;
data [ 8 ] = clk1224 ;
data [ 9 ] = date_fmt ;
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_SET_REAL_TIME_CLOCK , 0 , data , 10 ) ;
2011-07-23 18:26:16 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_set_vibrate_mode ( mwdevice_t * mwdevice , unsigned char enable , unsigned short on_time , unsigned short off_time , unsigned char cycles )
2011-07-23 18:26:16 +02:00
{
unsigned char mdata [ 7 ] ;
mdata [ 0 ] = enable ;
* ( unsigned short * ) ( mdata + 1 ) = on_time ; /* miliseconds */
* ( unsigned short * ) ( mdata + 3 ) = off_time ; /* miliseconds */
mdata [ 5 ] = cycles ;
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_SET_VIBRATE_MODE , 0 , mdata , 6 ) ;
2011-07-23 18:26:16 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_configure_watch_mode ( mwdevice_t * mwdevice , unsigned char mode , unsigned char save , unsigned char timeout , unsigned char invert )
2011-07-23 18:26:16 +02:00
{
unsigned char mdata [ 3 ] ;
mdata [ 0 ] = timeout ; /* seconds */
mdata [ 1 ] = invert ; /* 0=normal, 1=invert */
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_CONFIGURE_MODE , ( mode & 0x0f ) | ( ( save & 0x01 ) < < 4 ) , mdata , 2 ) ;
2011-07-23 18:26:16 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_update_display ( mwdevice_t * mwdevice , unsigned char mode , unsigned char copy )
2011-07-23 18:26:16 +02:00
{
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_UPDATE_DISPLAY , ( mode & 0x0f ) | ( ( copy & 0x01 ) < < 4 ) , NULL , 0 ) ;
2011-07-23 17:56:24 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_load_template ( mwdevice_t * mwdevice , unsigned char mode , unsigned char template_select )
2011-07-23 19:08:06 +02:00
{
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_LOAD_TEMPLATE , ( mode & 0x0f ) , & template_select , 1 ) ;
2011-07-23 19:08:06 +02:00
}
/*
* send line for screen - mode mode from * buffer to watch , starting at display row row_offset
2011-08-13 13:22:22 +02:00
* this is only for digital LCD watch
2011-07-23 19:08:06 +02:00
*/
2011-08-13 13:22:22 +02:00
int mw_write_buffer ( mwdevice_t * mwdevice ,
2011-07-23 19:08:06 +02:00
unsigned char mode ,
2011-07-23 21:32:08 +02:00
unsigned char numlines , /* number of lines, 0=two lines or 1=one line */
2011-07-23 19:08:06 +02:00
unsigned char row_offset , /* start at row_offset in display, e.g. lower part in idle @31 */
unsigned char * buffer , int buflen )
{
unsigned char mdata [ 32 ] ;
2011-08-13 13:22:22 +02:00
if ( mwdevice - > devtype ! = MW_DEVICE_TYPE_DIGITAL & & mwdevice - > devtype ! = MW_DEVICE_TYPE_DEVB_DIGI )
return - 1 ;
2011-07-23 19:08:06 +02:00
buflen = 12 * ( buflen / 12 ) ; /* crop to 12 bytes */
if ( ( numlines = = 0 & & buflen < 12 ) | | ( numlines = = 1 & & buflen < 24 ) ) {
fprintf ( stderr , " mw_write_buffer: bufferlen does not match number of lines \n " ) ;
2011-08-13 13:22:22 +02:00
return - 1 ;
2011-07-23 19:08:06 +02:00
} ;
memset ( mdata , 0 , 32 ) ;
mdata [ 0 ] = row_offset ;
memcpy ( ( mdata + 1 ) , buffer , 12 ) ;
2011-07-23 21:32:08 +02:00
if ( numlines = = 0 ) {
mdata [ 13 ] = row_offset + 1 ;
memcpy ( ( mdata + 14 ) , ( buffer + 12 ) , 12 ) ;
2011-07-23 19:08:06 +02:00
} ;
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_WRITE_BUFFER , ( mode & 0x0f ) | ( ( ( numlines & 0x01 ) < < 4 ) & 0x10 ) , mdata , numlines ? 13 : 26 ) ;
2011-07-23 19:08:06 +02:00
}
2011-08-10 20:13:00 +02:00
/*
Options :
B0 : row select , 0 first row , 1 second row
B1 : display select , 0 upper OLED , 1 lower OLED
B2 : if 1 send an event upon completion
B3 . .4 : scroll type ,
B5 . .7 : unused
Scroll types :
B0 : First buffer in a chain of scroll buffers
B1 : Any buffer except first or last
B2 : Last buffer of a chain
B3 : reserved / unused
Payload :
0 : Start index col
1. . : data
*/
2011-08-13 13:22:22 +02:00
int mw_write_oled_buffer ( mwdevice_t * mwdevice ,
2011-08-10 20:13:00 +02:00
unsigned char mode , /* idle or scroll */
unsigned char oled , /* which OLED */
unsigned char numcols ,
unsigned char col_index , /* starting index */
unsigned char * buffer , int buflen )
{
unsigned char mdata [ 32 ] ;
int i ;
2011-08-13 13:22:22 +02:00
if ( mwdevice - > devtype ! = MW_DEVICE_TYPE_ANA_DIGI & & mwdevice - > devtype ! = MW_DEVICE_TYPE_DEVB_ANA_DIGI )
return - 1 ;
2011-08-10 20:13:00 +02:00
2011-08-27 20:38:16 +02:00
fprintf ( stderr , " write oled buf len = %d \n " , buflen ) ;
2011-08-10 20:13:00 +02:00
/* lower row first since display wil be updated after completion of upper row */
if ( buflen > 80 ) {
for ( i = 80 ; i < buflen ; i + = 20 ) {
mdata [ 0 ] = ( i - 80 ) ;
memcpy ( ( mdata + 1 ) , ( buffer + i ) , 20 ) ;
2011-08-13 13:22:22 +02:00
mw_send_frame ( mwdevice , MW_WRITE_OLED_IDLE_DISPLAY_MSG , 0 | ( oled ? 2 : 0 ) , mdata , 21 ) ;
2011-08-10 20:13:00 +02:00
}
}
for ( i = 0 ; i < 80 ; i + = 20 ) {
mdata [ 0 ] = i ;
memcpy ( ( mdata + 1 ) , ( buffer + i ) , 20 ) ;
2011-08-13 13:22:22 +02:00
mw_send_frame ( mwdevice , MW_WRITE_OLED_IDLE_DISPLAY_MSG , 1 | ( oled ? 2 : 0 ) , mdata , 21 ) ;
2011-08-10 20:13:00 +02:00
}
2011-08-27 20:38:16 +02:00
2011-08-13 13:22:22 +02:00
return 0 ;
2011-08-10 20:13:00 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_enable_button ( mwdevice_t * mwdevice ,
2011-08-03 00:50:24 +02:00
unsigned char mode ,
unsigned char button_index ,
unsigned char press_type ,
unsigned char callback_type ,
unsigned char callback_option )
{
unsigned char mdata [ 32 ] ;
memset ( mdata , 0 , 32 ) ;
mdata [ 0 ] = mode ;
mdata [ 1 ] = button_index ;
mdata [ 2 ] = press_type ;
mdata [ 3 ] = callback_type ;
mdata [ 4 ] = callback_option ;
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_ENABLE_BUTTON , 0 , mdata , 5 ) ;
2011-08-03 00:50:24 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_disable_button ( mwdevice_t * mwdevice ,
2011-08-03 00:50:24 +02:00
unsigned char mode ,
unsigned char button_index ,
unsigned char press_type )
{
unsigned char mdata [ 32 ] ;
memset ( mdata , 0 , 32 ) ;
mdata [ 0 ] = mode ;
mdata [ 1 ] = button_index ;
mdata [ 2 ] = press_type ;
2011-08-13 13:22:22 +02:00
return mw_send_frame ( mwdevice , MW_ENABLE_BUTTON , 0 , mdata , 3 ) ;
2011-08-03 00:50:24 +02:00
}
2011-07-23 19:08:06 +02:00
2011-08-27 20:38:16 +02:00
int mw_advance_watch_hands ( mwdevice_t * mwdevice , unsigned char hours , unsigned char minutes , unsigned char seconds )
{
unsigned char mdata [ 4 ] ;
if ( hours > 12 )
return - 1 ;
if ( minutes > 60 )
return - 1 ;
if ( seconds > 60 )
return - 1 ;
mdata [ 0 ] = hours ;
mdata [ 1 ] = minutes ;
mdata [ 2 ] = seconds ;
return mw_send_frame ( mwdevice , MW_ADVANCE_WATCH_HANDS , 0 , mdata , 3 ) ;
}
2011-07-24 17:27:28 +02:00
/* ----------------------------------------------------------------------
* Watch responses , events or notifications
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-07-23 19:08:06 +02:00
2011-08-27 20:38:16 +02:00
int mw_get_device_type_response ( mwdevice_t * mwdevice , unsigned char devtype )
{
# ifdef DEBUG
fprintf ( stderr , " Got device type " ) ;
switch ( devtype ) {
case 0 :
fprintf ( stderr , " Reserved \n " ) ;
break ;
case 1 :
fprintf ( stderr , " Ana-Digi \n " ) ;
break ;
case 2 :
fprintf ( stderr , " Digital \n " ) ;
break ;
case 3 :
fprintf ( stderr , " Development Board Digital \n " ) ;
break ;
case 4 :
fprintf ( stderr , " Development Board Ana-Digi \n " ) ;
break ;
default :
fprintf ( stderr , " unknown %d \n " , devtype ) ;
break ;
} ;
# endif
mwdevice - > devtype = devtype ;
if ( mwdevice - > mw_get_device_type_response_cb ! = NULL )
mwdevice - > mw_get_device_type_response_cb ( mwdevice , devtype , mwdevice - > mw_gdtypersp_data ) ;
return 0 ;
}
void mw_set_get_device_type_response_cb ( mwdevice_t * mwdevice , void ( * mw_get_device_type_response_cb ) ( mwdevice_t * mwdevice , unsigned char devtype , void * user_data ) , void * user_data )
{
if ( mw_get_device_type_response_cb ! = NULL )
mwdevice - > mw_get_device_type_response_cb = mw_get_device_type_response_cb ;
if ( user_data ! = NULL )
mwdevice - > mw_gdtypersp_data = user_data ;
}
2011-08-13 13:22:22 +02:00
int mw_get_real_time_clock_response ( mwdevice_t * mwdevice , unsigned char * rtcrsp , int len )
2011-07-23 17:56:24 +02:00
{
struct tm mtm ;
unsigned short year ;
unsigned char clk1224 , date_fmt ;
if ( len ! = 10 ) {
2011-08-05 22:15:09 +02:00
fprintf ( stderr , " get real time clock response length wrong %d != 10 \n " , len ) ;
2011-08-13 13:22:22 +02:00
return - 1 ;
2011-07-23 17:56:24 +02:00
}
year = * ( unsigned short * ) rtcrsp ;
mtm . tm_year = year - 1900 ;
mtm . tm_mon = rtcrsp [ 2 ] - 1 ;
mtm . tm_mday = rtcrsp [ 3 ] ;
mtm . tm_wday = rtcrsp [ 4 ] ;
mtm . tm_hour = rtcrsp [ 5 ] ;
mtm . tm_min = rtcrsp [ 6 ] ;
mtm . tm_sec = rtcrsp [ 7 ] ;
clk1224 = rtcrsp [ 8 ] ;
date_fmt = rtcrsp [ 9 ] ;
2011-08-13 13:22:22 +02:00
# ifdef DEBUG
2011-07-23 17:56:24 +02:00
fprintf ( stderr , " watch RTC is %s, clock format is %s, date format is %s \n " , asctime ( & mtm ) , clk1224 ? " 24h " : " AM/PM " , date_fmt ? " DD/MM " : " MM/DD " ) ;
2011-08-13 13:22:22 +02:00
# endif
if ( mwdevice - > mw_get_real_time_clock_response_cb ! = NULL )
mwdevice - > mw_get_real_time_clock_response_cb ( mwdevice , & mtm , mwdevice - > mw_grtcrsp_data ) ;
return 0 ;
2011-07-23 17:56:24 +02:00
}
2011-08-13 13:22:22 +02:00
void mw_set_get_real_time_clock_response_cb ( mwdevice_t * mwdevice , void ( * mw_get_real_time_clock_response_cb ) ( mwdevice_t * mwdevice , struct tm * mw_tm , void * user_data ) , void * user_data )
{
if ( mw_get_real_time_clock_response_cb ! = NULL )
mwdevice - > mw_get_real_time_clock_response_cb = mw_get_real_time_clock_response_cb ;
if ( user_data ! = NULL )
mwdevice - > mw_grtcrsp_data = user_data ;
}
int mw_get_battery_voltage_response ( mwdevice_t * mwdevice , unsigned char * batrsp , int len )
2011-07-23 17:56:24 +02:00
{
unsigned short voltage = * ( unsigned short * ) batrsp ;
unsigned char power_good = batrsp [ 2 ] ;
unsigned char bat_charging = batrsp [ 3 ] ;
2011-08-13 13:22:22 +02:00
# ifdef DEBUG
fprintf ( stderr , " battery is at %dmV, %s and %s \n " , voltage , power_good ? " power is good " : " power fault " , bat_charging ? " charging " : " not charging " ) ;
# endif
if ( mwdevice - > mw_get_battery_voltage_response_cb ! = NULL )
mwdevice - > mw_get_battery_voltage_response_cb ( mwdevice , & voltage , & power_good , & bat_charging , mwdevice - > mw_gbatvrsp_data ) ;
return 0 ;
}
void mw_set_get_battery_voltage_response_cb ( mwdevice_t * mwdevice , void ( * mw_get_battery_voltage_response_cb ) ( mwdevice_t * mwdevice , unsigned short * voltage , unsigned char * pgood , unsigned char * charging , void * user_data ) , void * user_data )
{
if ( mw_get_battery_voltage_response_cb ! = NULL )
mwdevice - > mw_get_battery_voltage_response_cb = mw_get_battery_voltage_response_cb ;
if ( user_data ! = NULL )
mwdevice - > mw_gbatvrsp_data = user_data ;
2011-07-23 17:56:24 +02:00
}
2011-08-13 13:22:22 +02:00
int mw_read_button_config_response ( mwdevice_t * mwdevice , unsigned char * btnrsp , int len )
2011-08-03 00:50:24 +02:00
{
2011-08-13 13:22:22 +02:00
# ifdef DEBUG
2011-08-03 00:50:24 +02:00
fprintf ( stderr , " read button config response \n " ) ;
fprintf ( stderr , " screen mode : 0x%02x \n " , btnrsp [ 0 ] ) ;
fprintf ( stderr , " button index : 0x%02x \n " , btnrsp [ 1 ] ) ;
fprintf ( stderr , " mask table : 0x%02x ( " , btnrsp [ 2 ] ) ;
fprintf ( stderr , " %s " , ( btnrsp [ 2 ] & 0x01 ) ? " Absolute, " : " " ) ;
fprintf ( stderr , " %s " , ( btnrsp [ 2 ] & 0x02 ) ? " Press&Release, " : " " ) ;
fprintf ( stderr , " %s " , ( btnrsp [ 2 ] & 0x04 ) ? " Press&Hold, " : " " ) ;
fprintf ( stderr , " %s " , ( btnrsp [ 2 ] & 0x08 ) ? " Press&LongHold, " : " " ) ;
fprintf ( stderr , " %s " , ( btnrsp [ 2 ] & 0x10 ) ? " Immediate " : " " ) ;
fprintf ( stderr , " ) \n " ) ;
fprintf ( stderr , " callback msg type: 0x%02x \n " , btnrsp [ 3 ] ) ;
fprintf ( stderr , " callback msg opts: 0x%02d \n " , btnrsp [ 4 ] ) ;
2011-08-13 13:22:22 +02:00
# endif
return 0 ;
2011-08-03 00:50:24 +02:00
}
2011-08-13 13:22:22 +02:00
void mw_set_read_button_config_response_cb ( mwdevice_t * mwdevice , void ( * mw_read_button_config_response_cb ) ( mwdevice_t * mwdevice , void * user_data ) , void * user_data )
{
if ( mw_read_button_config_response_cb ! = NULL )
mwdevice - > mw_read_button_config_response_cb = mw_read_button_config_response_cb ;
if ( user_data ! = NULL )
mwdevice - > mw_rbtncnfrsp_data = user_data ;
}
int mw_read_light_sensor_response ( mwdevice_t * mwdevice , unsigned char * lightrsp , int len )
2011-07-30 17:22:05 +02:00
{
unsigned char power_good = lightrsp [ 0 ] ;
unsigned char bat_charging = lightrsp [ 1 ] ;
2011-08-13 13:22:22 +02:00
unsigned short light_level = * ( unsigned short * ) ( lightrsp + 2 ) ;
# ifdef DEBUG
fprintf ( stderr , " light sensor is at %d, power stat: %s and %s \n " , light_level , power_good ? " power is good " : " power fault " , bat_charging ? " charging " : " not charging " ) ;
# endif
if ( mwdevice - > mw_read_light_sensor_response_cb ! = NULL )
mwdevice - > mw_read_light_sensor_response_cb ( mwdevice , & light_level , mwdevice - > mw_rlsrsp_data ) ;
2011-07-30 17:22:05 +02:00
2011-08-13 13:22:22 +02:00
return 0 ;
2011-07-30 17:22:05 +02:00
}
2011-08-13 13:22:22 +02:00
void mw_set_read_light_sensor_response_cb ( mwdevice_t * mwdevice , void ( * mw_read_light_sensor_response_cb ) ( mwdevice_t * mwdevice , unsigned short * light_level , void * user_data ) , void * user_data )
2011-07-23 21:32:08 +02:00
{
2011-08-13 13:22:22 +02:00
if ( mw_read_light_sensor_response_cb ! = NULL )
mwdevice - > mw_read_light_sensor_response_cb = mw_read_light_sensor_response_cb ;
if ( user_data ! = NULL )
mwdevice - > mw_rlsrsp_data = user_data ;
}
int mw_status_change_event ( mwdevice_t * mwdevice , unsigned char option , unsigned char * statrsp , int len )
{
unsigned char mode = ( option & 0x0f ) ;
unsigned char status = statrsp [ 0 ] ;
2011-07-30 17:22:05 +02:00
# ifdef DEBUG
2011-07-23 21:32:08 +02:00
fprintf ( stderr , " Status change event for mode %s: %s \n " , mw_screen_mode_names [ option & 0x0f ] , mw_status_string [ statrsp [ 0 ] ] ) ;
2011-07-30 17:22:05 +02:00
# endif
2011-08-13 13:22:22 +02:00
if ( mwdevice - > mw_status_change_event_cb ! = NULL )
mwdevice - > mw_status_change_event_cb ( mwdevice , & mode , & status , mwdevice - > mw_stchev_data ) ;
return 0 ;
}
void mw_set_status_change_event_cb ( mwdevice_t * mwdevice , void ( * mw_status_change_event_cb ) ( mwdevice_t * mwdevice , unsigned char * scrmode , unsigned char * status , void * user_data ) , void * user_data )
{
if ( mw_status_change_event_cb ! = NULL )
mwdevice - > mw_status_change_event_cb = mw_status_change_event_cb ;
if ( user_data ! = NULL )
mwdevice - > mw_stchev_data = user_data ;
2011-07-23 21:32:08 +02:00
}
2011-07-24 17:27:28 +02:00
/* ----------------------------------------------------------------------
* Protocol handling
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-08-29 11:37:02 +02:00
int mw_decode_frame ( mwdevice_t * mwdevice , unsigned char * buf , int len )
2011-07-23 17:56:24 +02:00
{
unsigned short crc ;
unsigned char msglen ;
unsigned char msgtype ;
unsigned char msgopt ;
unsigned char * msgdata ;
2011-08-05 22:15:09 +02:00
unsigned char msgdatalen ;
2011-07-23 17:56:24 +02:00
/* check frame */
crc = * ( unsigned short * ) ( buf + len - 2 ) ;
if ( crc ! = crc16ccitt ( buf , len - 2 ) ) {
fprintf ( stderr , " decode frame CRC error \n " ) ;
2011-08-13 13:22:22 +02:00
return - 1 ;
2011-07-30 17:22:05 +02:00
}
2011-07-23 17:56:24 +02:00
if ( buf [ 0 ] ! = MW_SOF ) {
fprintf ( stderr , " decode frame SOF not found \n " ) ;
2011-08-13 13:22:22 +02:00
return - 1 ;
2011-07-30 17:22:05 +02:00
}
2011-07-23 17:56:24 +02:00
msglen = buf [ 1 ] ;
msgtype = buf [ 2 ] ;
msgopt = buf [ 3 ] ;
msgdata = ( buf + 4 ) ;
2011-08-05 22:15:09 +02:00
msgdatalen = msglen - 4 - 2 ;
2011-07-23 17:56:24 +02:00
switch ( msgtype ) {
2011-07-30 17:22:05 +02:00
case MW_GET_DEVICE_TYPE_RSP :
2011-08-27 20:38:16 +02:00
mw_get_device_type_response ( mwdevice , msgdata [ 0 ] ) ;
2011-07-23 17:56:24 +02:00
break ;
case MW_GET_INFORMATION_STRING_RSP :
2011-07-30 17:22:05 +02:00
msgdata [ len - 2 ] = 0 ;
fprintf ( stderr , " Got info string '%s' \n " , msgdata ) ;
break ;
case MW_GET_REAL_TIME_CLOCK_RSP :
2011-08-13 13:22:22 +02:00
mw_get_real_time_clock_response ( mwdevice , msgdata , msgdatalen ) ;
2011-07-23 17:56:24 +02:00
break ;
case MW_READ_BATTERY_VOLTAGE_RSP :
2011-08-13 13:22:22 +02:00
mw_get_battery_voltage_response ( mwdevice , msgdata , msgdatalen ) ;
2011-07-30 17:22:05 +02:00
break ;
case MW_READ_LIGHT_SENSOR_RSP :
2011-08-13 13:22:22 +02:00
mw_read_light_sensor_response ( mwdevice , msgdata , msgdatalen ) ;
2011-07-23 17:56:24 +02:00
break ;
case MW_LOW_BATTERY_WARNING_MSG :
fprintf ( stderr , " Watch battery low, please connect charger \n " ) ;
break ;
2011-08-03 00:50:24 +02:00
case MW_READ_BUTTON_CONFIG_RSP :
2011-08-13 13:22:22 +02:00
mw_read_button_config_response ( mwdevice , msgdata , msgdatalen ) ;
2011-08-03 00:50:24 +02:00
break ;
case MW_BUTTON_EVENT_MESSAGE :
fprintf ( stderr , " Button event message \n " ) ;
break ;
2011-07-23 17:56:24 +02:00
case MW_LOW_BATTERY_BT_OFF_MSG :
fprintf ( stderr , " Watch battery extremely low - radio will turn off \n " ) ;
break ;
2011-07-23 21:32:08 +02:00
case MW_STATUS_CHANGE_EVENT :
2011-08-13 13:22:22 +02:00
mw_status_change_event ( mwdevice , msgopt , msgdata , msgdatalen ) ;
2011-07-23 21:32:08 +02:00
break ;
2011-07-23 17:56:24 +02:00
default :
fprintf ( stderr , " Unkown msgtype 0x%02x \n " , msgtype ) ;
break ;
} ;
2011-08-13 13:22:22 +02:00
return msglen ;
2011-07-19 12:31:32 +02:00
}
2011-07-18 22:33:40 +02:00
2011-08-29 11:37:02 +02:00
int mw_feed_msg_buffer ( mwdevice_t * mwdevice , unsigned char * buf , int len )
{
char msgbuf [ 64 ] ;
int tlen ;
if ( len < = 0 )
return - 1 ;
memcpy ( ( mwdevice - > pbuf + mwdevice - > pbuf_len ) , buf , len ) ;
mwdevice - > pbuf_len + = len ;
while ( mwdevice - > pbuf_len > 0 ) {
/* scan for MW_SOF */
while ( mwdevice - > pbuf [ 0 ] ! = MW_SOF ) {
memmove ( mwdevice - > pbuf , ( mwdevice - > pbuf + 1 ) , - - mwdevice - > pbuf_len ) ;
}
tlen = mwdevice - > pbuf [ 1 ] ;
/* OK, there is an SOF but the message is too short */
if ( tlen > mwdevice - > pbuf_len ) {
/* we have to wait for more data to come in */
break ;
}
/* here we have a complete msg */
memcpy ( msgbuf , mwdevice - > pbuf , tlen ) ;
mw_decode_frame ( mwdevice , msgbuf , tlen ) ;
memmove ( mwdevice - > pbuf , ( mwdevice - > pbuf + tlen ) , tlen ) ;
mwdevice - > pbuf_len - = tlen ;
}
return 0 ;
}
2011-08-13 13:22:22 +02:00
/* ----------------------------------------------------------------------
* General code usage
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int mw_init ( mwdevice_t * mwdevice , int mw_fd )
{
memset ( mwdevice , 0 , sizeof ( mwdevice_t ) ) ;
mwdevice - > mw_fd = mw_fd ;
2011-08-29 11:37:02 +02:00
memset ( mwdevice - > pbuf , 0 , MW_PBUF_LEN ) ;
mwdevice - > pbuf_len = 0 ;
2011-08-13 13:22:22 +02:00
/* figure out which device we run with */
mw_send_frame ( mwdevice , MW_GET_DEVICE_TYPE , 0 , NULL , 0 ) ;
return 0 ;
}
2011-07-24 17:27:28 +02:00
/* ----------------------------------------------------------------------
* Convenience functions not strictly part of the protocol
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-07-23 21:32:08 +02:00
2011-08-13 13:22:22 +02:00
int mw_get_resolution ( mwdevice_t * mwdevice , unsigned int * width , unsigned int * height )
{
if ( width = = NULL | | height = = NULL )
return - 1 ;
switch ( mwdevice - > devtype ) {
case MW_DEVICE_TYPE_RESERVED :
return - 1 ;
case MW_DEVICE_TYPE_ANA_DIGI :
case MW_DEVICE_TYPE_DEVB_ANA_DIGI :
* width = 80 ;
* height = 16 ;
break ;
case MW_DEVICE_TYPE_DIGITAL :
case MW_DEVICE_TYPE_DEVB_DIGI :
* width = 96 ;
* height = 96 ;
break ;
default :
break ;
} ;
return 0 ;
}
2011-07-24 17:27:28 +02:00
/* if flip=1 bits in each byte are inverted 7->1, 6->2, 5->3,...
if invert = 1 each byte is inverted
*/
void bmap_buffer_flipinvert ( unsigned char flip , unsigned char invert , unsigned char * buf , int len )
2011-07-23 21:32:08 +02:00
{
int i ;
unsigned char tmp ;
while ( len - - ) {
tmp = 0 ;
2011-07-24 17:27:28 +02:00
if ( flip ) {
for ( i = 0 ; i < 8 ; i + + )
tmp | = ( ( * buf & ( 1 < < i ) ) > > i ) < < ( 7 - i ) ;
// fprintf(stderr, "0x%02x -> 0x%02x\n", *buf, tmp);
} else
tmp = * buf ;
2011-07-23 21:32:08 +02:00
* buf = invert ? ~ tmp : tmp ;
buf + + ;
}
}
2011-07-24 17:27:28 +02:00
2011-08-13 13:22:22 +02:00
void mw_send_bitmap ( mwdevice_t * mwdevice , unsigned char mode , int width , int height , int offset , unsigned char * bmapbuf , int buflen )
2011-07-23 21:32:08 +02:00
{
2011-07-30 17:22:05 +02:00
# ifdef DEBUG
unsigned int i , x ;
# endif
unsigned int y , rowlength ;
2011-07-23 21:32:08 +02:00
unsigned char mw_buf [ 24 ] ;
2011-07-30 22:45:11 +02:00
rowlength = ( ( ( width - 1 ) / 8 ) + 1 ) ;
2011-07-24 17:27:28 +02:00
if ( ( height + offset ) > 96 )
height = 96 - offset ;
2011-07-23 21:32:08 +02:00
2011-07-24 17:27:28 +02:00
# ifdef DEBUG
fprintf ( stderr , " row length = %d bytes \n " , rowlength ) ;
fprintf ( stderr , " bitmap resolution is %d x %d \n " , width , height ) ;
2011-07-23 21:32:08 +02:00
fprintf ( stderr , " \n " ) ;
for ( y = 0 ; y < height ; y + + ) {
for ( x = 0 ; x < rowlength ; x + + ) {
for ( i = 0 ; i < 8 ; i + + )
fprintf ( stderr , " %c " , ( bmapbuf [ ( y * rowlength ) + x ] & ( 1 < < ( 7 - i ) ) ) ? ' . ' : ' ' ) ;
}
fprintf ( stderr , " \n " ) ;
}
fprintf ( stderr , " \n " ) ;
# endif
for ( y = 0 ; y < height ; y + = 2 ) {
memset ( mw_buf , 0 , 24 ) ;
memcpy ( mw_buf , ( bmapbuf + ( y * rowlength ) ) , ( rowlength > 12 ) ? 12 : rowlength ) ;
memcpy ( ( mw_buf + 12 ) , ( bmapbuf + ( ( y + 1 ) * rowlength ) ) , ( rowlength > 12 ) ? 12 : rowlength ) ;
2011-08-13 13:22:22 +02:00
mw_write_buffer ( mwdevice , mode , 0 , offset + y , mw_buf , 24 ) ;
2011-07-23 17:56:24 +02:00
}
2011-07-19 14:13:11 +02:00
}