今回はHTC Desireに備わっているLED(カメラ撮影用フラッシュ)をネイティブから制御してON/OFFしてみる。
まずはHTC Developerセンターhttps://developer.htc.com/からDesireのソースコードをダウンロードする。今回は「bravo-2.6.32-gd96f2c0.tar.gz」でした。
ダウンロードしている間に雛形となるプロジェクトをEasyProjectGenerator for Androidで作る。今回はC++プロジェクトとした。
そして自動生成されたプロジェクトのjniフォルダに、ダウンロードしたHTC Desireのソースコードに含まれるmsm_camera.hをコピーする。
具体的なパスは「bravo-2.6.32-gd96f2c0\ include\ media\ msm_camera.h」。スクリーンキャプチャ用の環境ではtar.gzを解凍できなかったので別PCで解凍してコピーしてきました。
次にEclipseでプロジェクトを読み込んで実際にLEDを制御するコードを実装する。
#if(true) #define LOCAL_LOG #define LOCAL_LOGD #endif #include <string.h> #include <jni.h> #ifdef LOCAL_LOG #include <android/log.h> #endif #include <stdlib.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/syscall.h> #include "msm_camera.h" /* //msm_camera.hより #define MSM_CAM_IOCTL_MAGIC 'm' #define MSM_CAM_IOCTL_FLASH_LED_CFG _IOW(MSM_CAM_IOCTL_MAGIC, 22, unsigned *) #define MSM_CAMERA_LED_OFF 0 #define MSM_CAMERA_LED_LOW 1 #define MSM_CAMERA_LED_HIGH 2 #define MSM_CAMERA_LED_LOW_FOR_SNAPSHOT 3 */ // // フラッシュコントロール // //nModeはMSM_CAMERA_LED_OFF、MSM_CAMERA_LED_LOW、MSM_CAMERA_LED_HIGHなど // //事前に↓を実行すること! // "chmod 666 /dev/msm_camera/config0" // int CtrlCameraLED(int nMode) { int fd; int nRet; fd = open("/dev/msm_camera/config0",O_RDWR | O_NONBLOCK); if(fd < 0) return 0; msm_camsensor_info info; memset(&info,0,sizeof(info)); nRet = ioctl(fd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&info); if(nRet < 0 || info.flash_enabled == 0) { close(fd); return 0; } nRet = ioctl(fd,MSM_CAM_IOCTL_FLASH_LED_CFG,&nMode); close(fd); if(nRet < 0) return 0; return 1; } // //フラッシュをサポートしないなら0、サポートするなら0以外を返す // //事前に↓を実行すること! // "chmod 666 /dev/msm_camera/config0" // int IsSupportCameraLED(void) { int fd; int nOnOff; //uint_32 int nRet; msm_camsensor_info info; fd = open("/dev/msm_camera/config0",O_RDWR | O_NONBLOCK); if(fd < 0) return 0; memset(&info,0,sizeof(info)); nRet = ioctl(fd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&info); close(fd); if(nRet < 0) return 0; if(info.flash_enabled) return 1; return 0; } // // カメラセンサー名の取得 // //事前に↓を実行すること! // "chmod 666 /dev/msm_camera/config0" // int GetCameraSensorName(char* pszName,int nLen) { int fd; int nOnOff; //uint_32 int nRet; msm_camsensor_info info; if(nLen < MAX_SENSOR_NAME) return 0; fd = open("/dev/msm_camera/config0",O_RDWR | O_NONBLOCK); if(fd < 0) return 0; memset(&info,0,sizeof(info)); nRet = ioctl(fd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&info); close(fd); if(nRet < 0) return 0; strcpy(pszName,info.name); return 1; } extern "C" jboolean Java_com_Test132_Test132Act_NativeIsSupportCameraLED(JNIEnv* env,jobject thiz) { if(IsSupportCameraLED) return JNI_TRUE; return JNI_FALSE; } extern "C" jboolean Java_com_Test132_Test132Act_NativeCtrlCameraLED(JNIEnv* env,jobject thiz,jint nMode) { if(CtrlCameraLED(nMode)) return JNI_TRUE; return JNI_FALSE; } extern "C" jstring Java_com_Test132_Test132Act_NativeGetSensorName(JNIEnv* env,jobject thiz) { char pszName[MAX_SENSOR_NAME]; if(GetCameraSensorName(pszName,MAX_SENSOR_NAME) == 0) return env->NewStringUTF("Failed"); return env->NewStringUTF(pszName); }
java側では、画面をタッチしたら順々にLEDの光量を変更するようにします。
また、/dev/msm_camera/config0を開くには事前にRW属性を付けておかないといけない&RW属性を付けるにはroot権限が必要なので、suコマンドによりchmodを実行する関数も作っておきます。
これで実機で実行すると、、、package com.Test132; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.widget.TextView; public class Test132Act extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ExecSuCommand("chmod 666 /dev/msm_camera/config0"); NativeCtrlCameraLED(_nCurrentMode); TextView tv = new TextView(this); tv.setText( NativeGetSensorName() ); setContentView(tv); } boolean ExecSuCommand(String strCommandLine) { try { Process process = Runtime.getRuntime().exec("su"); java.io.DataOutputStream os = new java.io.DataOutputStream(process.getOutputStream()); os.writeBytes(strCommandLine + "\nexit\n"); os.flush(); process.waitFor(); return true; } catch(java.io.IOException e) { } catch (InterruptedException e) { } return false; } int _nCurrentMode = MSM_CAMERA_LED_OFF; final static int MSM_CAMERA_LED_OFF = 0; final static int MSM_CAMERA_LED_LOW = 1; final static int MSM_CAMERA_LED_HIGH = 2; final static int MSM_CAMERA_LED_LOW_FOR_SNAPSHOT = 3; @Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: switch(_nCurrentMode) { case MSM_CAMERA_LED_OFF: _nCurrentMode = MSM_CAMERA_LED_LOW; break; case MSM_CAMERA_LED_LOW: _nCurrentMode = MSM_CAMERA_LED_HIGH; break; case MSM_CAMERA_LED_HIGH: _nCurrentMode = MSM_CAMERA_LED_LOW_FOR_SNAPSHOT; break; case MSM_CAMERA_LED_LOW_FOR_SNAPSHOT: _nCurrentMode = MSM_CAMERA_LED_OFF; break; } NativeCtrlCameraLED(_nCurrentMode); break; } return true; } public native boolean NativeIsSupportCameraLED(); public native boolean NativeCtrlCameraLED(int nMode); public native String NativeGetSensorName(); static { System.loadLibrary("Test132"); } }

すると画面にカメラセンサー名の「s5k3e2fx」という文字が表示されて、画面をタッチすると、、、
成功のように思えるのですが、何度タッチしても光量が変わりません。本当なら3段階&OFFの4パターンが順々に変化するはずなのですが、、
プロジェクトファイルをダウンロード