/*
* TOPPERS/JSP Kernel
* Toyohashi Open Platform for Embedded Real-Time Systems/
* Just Standard Profile Kernel
*
* Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
* Toyohashi Univ. of Technology, JAPAN
*
* 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
* によって公表されている GNU General Public License の Version 2 に記
* 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
* を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
* 利用と呼ぶ)することを無償で許諾する.
* (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
* 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
* スコード中に含まれていること.
* (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
* 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
* 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
* の無保証規定を掲載すること.
* (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
* 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
* と.
* (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
* 作権表示,この利用条件および下記の無保証規定を掲載すること.
* (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
* 報告すること.
* (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
* 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
*
* 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
* よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
* 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
* 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
*
* @(#) $Id: hw_serial.c,v 1.13 2003/12/15 07:19:22 takayuki Exp $
*/
#include <hw_serial.h>
#include <hal_msg.h>
#include <t_services.h>
#include <resource.h>
#include <debugout.h>
#define BUFSZ_UPPERBOUND 24*1024 /* コンソールバッファの巻戻し基準サイズ (これを超えると巻き戻し) (どうやら30000を超えられないらしい)*/
#define BUFSZ_LOWERBOUND 8*1024 /* 巻き戻したときにどのくらい巻き戻すか (UPPERBOUNDよりも小さい数)*/
#define ID_PORT(x) ((x) + 1)
#define INDEX_PORT(x) ((x) - 1)
#define GET_SIOPCB(x) (&siopcb_table[INDEX_PORT(x)])
#define BITTEST(x,y) ( ( (x) & (y) ) != 0)
#define BITSET(x,y) InterlockedExchange( &(x), (x) | (y) )
#define BITCLEAR(x,y) InterlockedExchange( &(x), (x) & ~(y) )
extern HINSTANCE ProcessInstance;
extern HANDLE PrimaryThreadHandle;
/* シリアル制御ブロック */
SIOPCB siopcb_table[TNUM_PORT];
/* 致命的なエラー発生時用アサート */
extern void FatalAssertion(int exp, LPCSTR format, ... );
/*
* シリアルI/O共通部インタフェース
*/
/*===========================================================================*/
/*
* コンソール型シリアル
*/
#define MAX_CONSOLE_BUFSZ 2048
#define SERMSG_CREATE WM_APP
#define SERMSG_UPDATE (WM_APP+1)
struct tagSerialConsoleParameters
{
CRITICAL_SECTION cs;
unsigned int position;
char buffer[MAX_CONSOLE_BUFSZ];
};
static LRESULT CALLBACK KeyEventTrapper(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
SIOPCB * scope;
/* WM_CHARをフックする */
if(Msg == WM_CHAR)
{
scope = (SIOPCB *)GetWindowLong(GetParent(hWnd),GWL_USERDATA);
PostMessage(scope->Handle,WM_CHAR,wParam,lParam);
return TRUE;
}
/* もともとのWndProcを呼びなおす */
return CallWindowProc((void *)GetWindowLong(hWnd,GWL_USERDATA),hWnd,Msg,wParam,lParam);
}
static void SelectConsoleFont(HWND console, UINT pixel)
{
HANDLE oldfont;
HANDLE newfont;
LOGFONT logfont;
HDC hDC;
/* DC取得 */
hDC = GetDC(console);
/* 今のフォント情報を取得する */
oldfont = (HANDLE) SendMessage(console, WM_GETFONT, 0, 0);
GetObject(oldfont, sizeof(LOGFONT), &logfont);
/* ポイントを変更 */
logfont.lfHeight = -MulDiv(pixel, GetDeviceCaps(hDC, LOGPIXELSY), 72);
/* 更新したフォント情報を元に、新しいフォントを生成して選択 */
newfont = CreateFontIndirect(&logfont);
SendMessage(console, WM_SETFONT, (WPARAM)newfont, MAKELPARAM(TRUE,0));
/* 前のフォントを破棄 */
DeleteObject(oldfont);
/* DC解放 */
ReleaseDC(console, hDC);
}
static LRESULT ConsoleCommandHandler(HWND hDlg, UINT wID, UINT wNotifyCode, LPARAM lParam)
{
BOOL result;
HANDLE console;
result = TRUE;
console = GetDlgItem(hDlg, IDC_CONSOLE);
switch(wID)
{
/*
* フォントの大きさを変更する
*/
case ID_FONT_BIG:
SelectConsoleFont(console, 16);
break;
case ID_FONT_NORMAL:
SelectConsoleFont(console, 9);
break;
case ID_FONT_SMALL:
SelectConsoleFont(console, 4);
break;
default:
result = FALSE;
}
return result;
}
static BOOL CALLBACK ConsoleProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)
{
switch(Msg)
{
case SERMSG_CREATE:
{
SIOPCB * work;
void * DefWndProc;
HWND hConsole;
hConsole = GetDlgItem(hDlg, IDC_CONSOLE);
/* テキストボックスのWndProcにフックをかける */
DefWndProc = (void *)GetWindowLong(hConsole,GWL_WNDPROC);
SetWindowLong(hConsole, GWL_USERDATA, (LONG) DefWndProc);
work = (SIOPCB *)lParam;
SetWindowLong(hDlg,GWL_USERDATA,lParam);
SetWindowLong(hConsole, GWL_WNDPROC, (long)KeyEventTrapper);
SetTimer(hDlg, 100, 300, NULL);
ShowWindow(hDlg,SW_SHOWNA);
break;
}
case WM_DESTROY:
{
SIOPCB * scope;
KillTimer(hDlg, 100);
scope = (SIOPCB *)GetWindowLong(hDlg,GWL_USERDATA);
if(scope != 0)
scope->Handle = NULL;
break;
}
case WM_CLOSE: /* ユーザによるウィンドウクローズを抑止 */
break;
case WM_CHAR:
{
SIOPCB * scope;
scope = (SIOPCB *)GetWindowLong(hDlg,GWL_USERDATA);
if(scope != 0)
{
scope->ReceiveBuffer = (char)wParam;
BITSET(scope->Flag, SIO_STA_INTRCV);
HALInterruptRequest(INHNO_SERIAL);
}
break;
}
case WM_SETFONT:
return TRUE;
case WM_INITDIALOG:
case WM_SIZE:
{
RECT client;
GetClientRect(hDlg,&client);
MoveWindow(GetDlgItem(hDlg,IDC_CONSOLE),0,0,client.right,client.bottom,TRUE);
break;
}
case WM_COMMAND:
return ConsoleCommandHandler(hDlg, LOWORD(wParam), HIWORD(wParam), lParam);
//一定時間たったら改行がこなくても出力する
case WM_TIMER:
if(wParam == 100)
{
SIOPCB * scope;
struct tagSerialConsoleParameters * param;
scope = (SIOPCB *)GetWindowLong(hDlg, GWL_USERDATA);
if(scope != 0) {
param = (struct tagSerialConsoleParameters *)scope->versatile;
if(param->position == 0)
break;
lParam = TRUE;
}
else
break; //まだ初期化が終わってないので何もしない
}
//lParam : 送信が終わった後に割込みをかけるかどうか (FALSE:かけない TRUE:かける)
case SERMSG_UPDATE:
{
LRESULT result;
int textlength;
HANDLE console;
SIOPCB * scope;
struct tagSerialConsoleParameters * param;
scope = (SIOPCB *)GetWindowLong(hDlg, GWL_USERDATA);
if(scope != 0) {
param = (struct tagSerialConsoleParameters *)scope->versatile;
console = GetDlgItem(hDlg, IDC_CONSOLE);
textlength = GetWindowTextLength(console);
if(textlength > BUFSZ_UPPERBOUND)
{
/* 古い情報を消す */
SendMessage(console,EM_SETSEL,0,textlength - BUFSZ_LOWERBOUND);
SendMessage(console,EM_REPLACESEL,(WPARAM)FALSE,(LPARAM)"");
textlength = GetWindowTextLength(console);
}
/* 末尾に文字を置く */
result = SendMessage(console,EM_SETSEL,textlength,textlength);
EnterCriticalSection(¶m->cs);
param->buffer[param->position] = '\x0';
result = SendMessage(console,EM_REPLACESEL,(WPARAM)FALSE,(LPARAM)param->buffer);
param->position = 0;
LeaveCriticalSection(¶m->cs);
if(lParam == TRUE)
{
BITSET(scope->Flag, SIO_STA_INTSND);
HALInterruptRequest(INHNO_SERIAL);
}