상황 : centos + mono + c# + postgresql
(postgresql 은 utf-8 로 db 및 테이블 생성했음)


euc-kr(cp949 ?) 데이터를 받을 일이 있어서 출력했는데 한글 부분 깨짐.
아마도 euc-kr 데이터라 유니코드 (혹은 utf-8)로 변환이 필요할 것으로 생각됨. 

그래서 코드변환하게 C# 프로그램에서 조금 수정

기존 :

System.Text.Encoding.Default.GetString(bytes);


변경 :

System.Text.Encoding.GetEncoding(51949).GetString(bytes); // 51949 대신 "euc-kr" 을 써도 되는 듯



그랬더니 오류 발생

Unhandled Exception: System.NotSupportedException: CodePage 51949 not supported


뭥미? 싶어서 구글링해보니 우분투 포럼에 있다. (http://ubuntuforums.org/showthread.php?t=831409)
대충 정리하면 mono용 i18n  깔아라~

음... 난 centos 니까
yum search mono
쭉 훑어보니
mono-locale-extras.i386 : Extra locale information for Mono
요놈이구나 !
yum install mono-locale-extras

오류 안남.

끝.

이면 좋으련만 그래도 db에 저장하는 한글은 깨져있음.
접속하는데 사용한 라이브러리는 mono용 npgsql 인데, 혹시 커넥션 파라미터(dsn)에 인코딩 지정하는 것 있나??

찾아보니 있다. 기본이 유니코드일 줄 알았는데 아니다.
ASCII가 기본이란다. UTF-8 쓰는데 지장있으면 UNICODE 지정하란다. (http://www.mono-project.com/PostgreSQL)

C# 코드의 npgsql 커넥션파라미터에 다음을 추가

Encoding=UNICODE


깔꼼하게 해결 ~ 쿼리 툴 따로 쓰기 귀찮아서 깔아놓은 phpPgAdmin 에도 한글이 잘 나온다.
 


참고한 페이지 :

http://funnism.com/11


http://msdn.microsoft.com/ko-kr/library/system.text.encoding.aspx
Posted by freezn
- 상황
1. HP DL120G7 모델을 납품용으로 구매
2. 250GB SATA * 2 을 레이드용으로 같이 구매
3. centos 5.X 를 설치하기로 마음 먹음

- 1차 시도 및 문제 발생
0. 공식 미러들에는 5.X 는 현재(2011-10-06) 최신 버전인 5.7만 제공되어 별 생각 없이 5.7 x86_64 netinstall 버전을 CD로 구움
1. F9 로 CMOS 들어가서 Advanced ~~ 에서 SATA RAID Controller ? 를 RAID 로 설정
2. 패키지에 제공된 Smart Setup CD로 250GB *2 를 RAID 1 설정 (부팅 중 F8로 해도 똑같음)

아나콘다에서 레이드를 인식 못하고 2개로 떠버림 ...?!?!?!? 

 황당해서 찾아보니 HP DL120G7 에 내장된 RAID 컨트롤러(B110i)는 이름만 컨트롤러(fake controller?)고 사실상 소프트웨어 레이드라고 함. 충돌도 많음(su*ks?) !?

- 2차 시도 및 다시 문제 발생
1. F9 로 CMOS 들어가서 Advanced ~~ 에서 SATA RAID Controller ? 를 RAID 로 설정
2. 패키지에 제공된 Smart Setup CD로 250GB *2 를 RAID 1 설정 (부팅 중 F8로 해도 똑같음)
3. CD 에 들어있던 hpahcisr-1.2.6-7.rhel5.x86_64.dd.gz 파일을 압출풀어서 usb에 넣고 다시 시도
3. 아나콘다 호출 전에  [enter]로 호출하지 않고 linux dd 로 호출해서 드라이버 설정창 띄움
4. /dev/sda4 식으로 잡히는데 여기서 저 파일(hpahcisr-1.2.6-7.rhel5.x86_64.dd)을 선택 (드라이버 로딩상황이 어째 좀 멜랑꼴리함)
5. 똑같음

- 3차 시도 및 다시 문제 발생
1. RAID 세팅해놓고 인스톨전에 전원꺼서 두번째 하드 빼고 os인스톨하고 hp 툴들 설치 후 다시 하드 꽂는 신공을 보고 따라해봄
2. hpahcisr-1.2.6-7.rhel5.x86_64.rpm 설치 안됨. 지원하지 않는 커널 버전이라고.
3. HP 홈페이지 뒤져서 5.7 에 해당하는 패치 버전(1.2.6-9) 찾아내서 설치 후 리부팅 (슬슬 원인을 알았지만 인정할 수 없었음)
4. 이상태까지에서 혹시 하고 확인해보니 hpacucli 에서 아예 컨트롤러 없다고 나옴
5. 부팅 중 커널패닉

 - 성공
1. hpahcisr-1.2.6-7.rhel5.x86_64.rpm 웹 설명 읽어보니 RHEL 5 updates 6 까지. (그럼 CD에 써놓던가...)
2. http://vault.centos.org 가서 centos 5.5 이미지 받아다 CD 구움
3. usb 에 넣어놓은  hpahcisr-1.2.6-7.rhel5.x86_64.dd 파일 이용해서 아나콘다 호출할 때 linux dd 해서 드라이버 로딩 (잘됨)
4. 굳이 하드 안빼고도 os 설치과정 다 정상
5. os 설치 후  부팅하고나서 hpahcisr-1.2.6-7.rhel5.x86_64.rpm 설치, hpacucli 도 설치 (둘다 smart setup cd에 들어있음. compaq/csp/linux에 rpm들, punchout에 dd 파일)

hpacucli 로 정상여부 확인
hpacucli ctrl slot=0 show config detail 
hpacucli ctrl slot=0 show status

ok.

커널패치 필요한건지 확인코자 다시해볼 엄두가 안들어서
그냥 yum 업데이트 꺼버림. -_-;;

-----------------

. HP 버럭!!!
. 홈페이지 검색엔진 안고칠래? !?!?!
. CD에 RHEL 몇용인지 안써놓냐!? (그냥 linux support)
. RHEL 5 update 7 대응 하는 hpahcisr-1.2.6-9.rhel5.x86_64.rpm 는  왜 커널패치만 있고 드라이버(dd)는 따로 없는거냐 대체..........................
Posted by freezn

# 커멘드 포트를 21말고 다른거 쓰려할 경우
listen_port=9021
 
# Passive Mode 활성화
pasv_enable=YES

# 가변 포트 범위.. 내맘..
pasv_min_port=40000
pasv_max_port=40010 

# NAT 외부 IP 주소.. 이거 이러면 DDNS 상황일때는 안되겠네?
pasv_address= 서버주소

 
Posted by freezn
웹서버에 올려둔 파일이 아이폰에서는 스트리밍되는데,
안드로이드에서는 안되는 경우

헤더의 위치가 문제라고 합니다.

많이 사용되는 인코더들이 파일정보(..헤더라며..왜 끝에..)를 끝에 붙여주는데 안드로이드는 이걸 인식하지 못한다고하네요.



mp4box 라는 툴로 mp4box -hint xxx.mp4 식으로 한번 헤더를 세팅해주니 해결됩니다..
Posted by freezn
이럴수가.

어째서 TouchCalibrate()를 호출해도 이 망할 프로그램이 실행되지 않으면서 바로 false를 리턴하는지에 대하여 고민 했는데

내가 작성한 내용은 SD로부터 캘값을 가져오는데 실패한다면 이 함수를 호출하는 것 이었고

당연하게도 캘값을 적용하기 위한 시점이니 터치 드라이버의 initial시점 전 이었다.

맙소사, 이걸 3일간 고민했단 말인가.

SD로부터 터치 캘리브레이션 값을 읽어오려 할 때 SD bus를 먼저 로딩시켜놨음에도 터치트라이버 init 단계에서 아직 sd가 인식되지 않은 문제는 터치 드라이버에 sleep 걸어서 대기 시켜놓은 방법으로 해결 ..ㅡㅡ;;

iPhone 에서 작성된 글입니다.
Posted by freezn

Visual Studio 2005에서 DLL을 확인하기 위해 dumpbin을 사용하려 했더니 mspdb80.dll을 찾을 수 없다는 아래와 같은 에러메세지가 나온다.


PATH가 안잡혀서 나는 에러겠지? 싶어서 찾아보니 답이 나왔다.
"C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
을 실행해주면 환경변수를 다 잡아준다 (편리해~)



아무거나 잡고 테스트


이거 뭐야.. 무서워..
Posted by freezn

빌드 시 에러

"~~~ fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?"

VC++외의 컴파일러에서 빌드하였거나 다른 스타일(obj c같은 경우?)로 작성된 라이브러리를 링크하면 위와 같은 건방지고 친절한(?) 에러가 발생하는 경우가 있다.

빠른 빌드를 위한 PCH (precompiled header)가 없어서 난다는데,

안내문대로 "stdafx.h"를 include 해주거나

project property -> Configuration Properties -> C/C++ -> Precompiled headers -> Create/Use Precompiled header 를
Not Using Precompiled Headers로 바꿔주면 된다.
(그전에는 아마 Use Precompiled Header (/Yu) 로 되어있을 것이다.)
Posted by freezn
개발 중 간혹 에뮬레이터와 ActiveSync를 시키고 싶을 수 있다.

이럴 때 유용한 내용. (아놔.. 나만 몰랐나보다)

ActiveSync의 연결설정에서 허용항목을 "DMA"로 선택하고,
Visual Studio 2005의 Tools -> Device Emulator Manager 에서 해당장치에 Cradle 명령을 준다.

Posted by freezn
Visual Studio 2005에서 Windows CE용 애플리케이션을 개발할 때 소스에는 오류가 없는데도 에러가 발생 할 경우가 있다.

이럴 때 이 놈을 의심 해본다.

기본 스택사이즈가 무려 64KB (65536 Byte)로 되어있다.

부족하다면 늘려주자.



디버그모드로는 잘되는데 릴리즈로 하면 실행하자마자 뻗어서 보니 디버그모드에만 설정해놨던 1인..orz
Posted by freezn

io control 은 장치를 file처럼 다루는 read, write, seek 등으로는 부족함을 느낄 때 사용하는 부분.

귀찮으면 그냥 read/write에 첫바이트는 기능 구분.. 나머지는 데이터... 뭐 이런 무식한 꽁수를 써도 문제는 없을 듯.

대략 초보용.

리눅스의 ioctl과 같은 기능임.

---

디바이스 드라이버

XXX_IOControl() 함수 머리

BOOL XXX_IOControl(
  DWORD dwInst, // 써본 적 없음. ISR handler 의 인스턴스라는데 -_-a
  DWORD dwIoControlCode, // IO Control 코드. 기능들로 분기 시키기 위한 코드.
  LPVOID lpInBuf, // 어플리케이션에서 넘겨주는 데이터 버퍼
  DWORD nInBufSize, // 그 크기
  LPVOID lpOutBuf, // 드라이버가 어플리케이션에게 건네줄 데이터 버퍼
  DWORD nOutBufSize, // 그 크기
  LPDWORD lpBytesReturned // 써본 적 없음. 오류 처리용인가보다 -_-;
)

일단 머리가 저렇게 생겼고 각 파라미터들의 용도는 저렇다. 아직 모르는건? 우짜나 -_-;

XXX_IOControl 함수 내용

 switch(dwIoControlCode)
 {
 case IOCTL_XXX_CMD_A :
  memcpy(myTemp, lpInBuf, nInBufSize);

  break;
 case IOCTL_XXX_CMD_B :
  memcpy(lpOutBuf, myTemp, nOutBufSize);
  break;

 case IOCTL_XXX_CMD_C :
  myFunc();
  break;

 default:
  RETAILMSG(1,(TEXT("XXX : unknown io control code! \n\r")));
  break;

}


보다시피 IOCTL_XXX_CMD_A, IOCTL_XXX_CMD_B, IOCTL_XXX_CMD_C 를 사용했다.

각각
IOCTL_XXX_CMD_A 는 어플리케이션이 주는 데이터를 myTemp 라는 임시공간에 저장하고,
IOCTL_XXX_CMD_B 는 myTemp에 있는 데이터를 어플리케이션에게 건네주는 기능이며,
IOCTL_XXX_CMD_C 는 다 필요없고 그냥 myFunc()라는 함수를 호출한다..

물론 실제 구현은 단순히 메모리를 복사하는 내용으로 끝나진 않겠지만 나머지 부분은 사용자의 목적에 맞게 구현하면 된다.

그럼 대체 이 switch case분기용 IOCTL_XXX_CMD_X 는 어떻게 만든 걸까?
여기서는 CTL_CODE라는 매크로가 사용된다.

CTL_CODE 는
#define CTL_CODE(DeviceType, Function, Method, Access) (
  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
)

이렇게 생겨먹었는데..
이건 각 기능에 대한 고유 ioctl번호를 생성하기 위한 매크로다.
[DeviceType][Access][Function][Method] 형태로 unsigned 4byte 짜리 숫자를 생성한다.
결과물이 어떤 값인지 알아도 좋지만 별로 알 필요는 없다. 매크로는 바뀌거나 바꿀 수도 있으므로 그냥 쓰면 된다.

CTL_CODE(DeviceType, Function, Method, Access) 이다.

DeviceType :
리눅스에서도 비슷한게 있다. 장치에 대한 번호다.
MSDN - CTL_CODE 페이지나 {winceroot}\public\common\oak\inc\windev.h 를 열어보면 명세들이 있다.
FILE_DEVICE_XXX 시리즈가 사용된다.
근데... MSDN을 잘보면 0~0x7FFF 까지는 지네거란다 ㅡ.ㅡ
우리같은 OEM들은 MS규격 장치의 드라이버를 만드는게 아니라면
0x8000 ~ 0xFFFF 를 쓰면 된단다.
저 중에 하나 정하자.

Function :
장치의 기능들에 대한 부분이다. 여기서도 0~0x7FF 는 MS에서 쓸거라니까
0x800 ~ 0xFFF 중에 구현할 장치의 기능 만큼 골라 쓰자 -_-;

Method :
이거 이제 안쓴단다. 무조건 METHOD_BUFFERED 만 쓰란다.
데스크탑용 Windows에서는 좀 다르니까 주의하란다.

Access :
읽기를 할까? FILE_READ_ACCESS
쓰기를 할까? FILE_WRITE_ACCESS
둘다할까? FILE_ANY_ACCESS
복잡하고 별로 무의미하니 걍 FILE_ANY_ACCESS 쓰면 될 것 같다.

그래서 내가 선언한 선언부는 이렇다. (드라이버 소스 시작단에 넣었다.)

#define MYDEVICE 0x8001
#define MYDEVICE_FUNC 0x800
#define IOCTL_XXX_CMD_A  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_B  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_C  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+3, METHOD_BUFFERED, FILE_ANY_ACCESS)


첫번째 DeviceType은 OEM용 장치타입 코드 영역인 0x8000~0xFFFF 중에 0x8001 을 골라썼고 (이건 장치마다)
두번째 Function 역시 OEM용 기능구분 코드 영역 0x800 ~ 0xFFF 에서 순서대로 0x801~0x803를 썼다. (이건 기능마다 달라야한다.)

그럼 이제 CTL_CODE도 만들었고, 드라이버 소스도 작성했으니 어플리케이션으로...

---

어플리케이션

어플리케이션에서도 CTL_CODE를 알아야한다. (저 매크로의 결과값을 옮겨도 되겠지만)
그러니 코드를 생성하는 매크로 부분을 어플리케이션 소스에도 복사한다. (혹은 같은 헤더파일로 공유한다.)

#define MYDEVICE 0x8001
#define MYDEVICE_FUNC 0x800
#define IOCTL_XXX_CMD_A  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_B  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_C  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+3, METHOD_BUFFERED, FILE_ANY_ACCESS)

어플리케이션의 헤더에 붙여넣고 자신만만하게 컴파일 시키면
CTL_CODE, METHOD_BUFFERED, FILE_ANY_ACCESS 가 정의된 적 없다고 컴파일러가 외친다.
여기서 나는 PB에서 제공하는 windev.h의 내용을 복사해다 붙여버릴까... 하는 충동을 느꼈지만 (실제로 그렇게 해보기도 했다.)
무식하게 하지 말자고 충동을 억누르고 어플리케이션에서 참조하는 SDK의 헤더를 뒤져봤다. (라고 쓰고 'editplus의 여러파일찾기'라고 읽는다.)

아싸. winioctl.h 에 다~~포함되어있다.
#include <winioctl.h> 을 CTL_CODE 정의부 위에 추가한다.

이제 DeviceIoControl 함수를 사용할 때 가 되었다.

BOOL DeviceIoControl(
  HANDLE hDevice, // 열어놓은 XXX 장치의 핸들
  DWORD dwIoControlCode, // 호출할 CTL_CODE
  LPVOID lpInBuffer, // 드라이버에게 넘겨줄 데이터 버퍼
  DWORD nInBufferSize,  // 그 크기
  LPVOID lpOutBuffer,  // 드라이버에게서 넘겨 받을 데이터 버퍼
  DWORD nOutBufferSize, // 그 크기
  LPDWORD lpBytesReturned, // XXX_IOControl에서의 lpBytesReturned 와 연결되는 놈이다. 난 몰라~~ -_-;
  LPOVERLAPPED lpOverlapped // 무시된다. NULL로 세팅할 것.
);

모양새는 저렇게 생겨먹었고,
사용해보자. (아래의 내용은 위 드라이버의 소스와 맞춰가며 보면 좋다.)

// lpBytesReturned 용이다. 난 안쓰는데 필요로 하길래 지정해줬다. 쳇 -_-;
DWORD bytes;

// IOCTL_XXX_CMD_A 를 호출한다.
// pWritrBuf 의 내용을 pWriteBuf의 크기만큼 드라이버에게 넘겨준다.
// 이 내용은 디바이스 드라이버의 XXX_IOControl 이 받아서,
// IOCTL_XXX_CMD_A 분기로 들어가고,
// myTemp에 여기서 건네주는 pWriteBuf의 데이터를 pWriteBuf의 크기만큼 memcpy하게 된다.
DeviceIoControl(hDev, IOCTL_XXX_CMD_A, pWriteBuf, sizeof(pWriteBuf), NULL, 0, &bytes, NULL);

// IOCTL_XXX_CMD_B 를 호출한다.
// pReadBuf 의 내용을 pReadBuf의 크기만큼 드라이버에게 넘겨준다.
// 이 내용은 디바이스 드라이버의 XXX_IOControl 이 받아서,
// IOCTL_XXX_CMD_B 분기로 들어가고,
// 디바이스 드라이버가 갖고 있던 myTemp의 내용을 pReadBuf에 pReadBuf의 크기만큼 memcpy 해준다.
// 그럼 드라이버에서 값을 가져왔으니 맘대로 쓰면 된다.
DeviceIoControl(hDev, IOCTL_XXX_CMD_B, NULL, 0, pReadBuf, sizeof(pReadBuf), &bytes, NULL);

// IOCTL_XXX_CMD_C 를 호출한다.
// 디바이스드라이버에  데이터 주고 받는 것 없이 명령을 내리는 거다.
// XXX_IOControl의 IOCTL_XXX_CMD_C 분기로 들어가서 myFunc(); 함수를 호출한다.
DeviceIoControl(hDev, IOCTL_XXX_CMD_C, NULL, 0, NULL, 0, &bytes, NULL);

---

이후의 의문

CTL_CODE 매크로 없이 IOControl Code를 0x01, 0x02 뭐 이런식으로 쓰면 안될까?
-> 되더라 -_-a 별 문제 없던데...
그럼 Function Code는?
-> 되더라 -_-a 이것도 별 문제 없던데... 귀찮게 스리 뭘 그리 정의 해놓고 그런건지.. ㅠㅠ
그럼 Method나 Access도 NULL 로 줘버리면?
-> 되더라 -_-a

위 내용으로 미루어봤을 때, CTL_CODE는 정말 단순히 충돌예방을 위해 각기능에 대한 고유번호를 매기는 매크로일 뿐이다.
사실 각 장치를 열어서 호출하는 것이니 만큼 충돌 날 일도 없을 걸로 예상되는데,
디버깅용으로 필요할 것 같다.

그래도 저렇게 하라고 msdn에 적어놨으니 귀찮지만 맞춰서 써주자.

---

- 끝 -

Posted by freezn