125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood/*
225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * Copyright (C) 2011 The Android Open Source Project
325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood *
425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * you may not use this file except in compliance with the License.
625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * You may obtain a copy of the License at
725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood *
825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood *
1025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * Unless required by applicable law or agreed to in writing, software
1125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
1225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * See the License for the specific language governing permissions and
1425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood * limitations under the License.
1525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood */
1625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
1725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodpackage com.android.serialchat;
1825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
1925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.app.Activity;
2025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.content.Context;
2125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.hardware.SerialManager;
2225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.hardware.SerialPort;
2325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.os.Bundle;
2425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.os.Handler;
2525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.os.Message;
2625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.os.ParcelFileDescriptor;
2725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.view.KeyEvent;
2825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.view.View;
2925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.view.inputmethod.EditorInfo;
3025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.util.Log;
3125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.widget.EditText;
3225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport android.widget.TextView;
3325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
3425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport java.nio.ByteBuffer;
3525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodimport java.io.IOException;
3625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
3725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwoodpublic class SerialChat extends Activity implements Runnable, TextView.OnEditorActionListener {
3825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
3925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private static final String TAG = "SerialChat";
4025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
4125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private TextView mLog;
4225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private EditText mEditText;
4325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private ByteBuffer mInputBuffer;
4425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private ByteBuffer mOutputBuffer;
4525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private SerialManager mSerialManager;
4625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private SerialPort mSerialPort;
4725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private boolean mPermissionRequestPending;
4825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
4925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    private static final int MESSAGE_LOG = 1;
5025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
5125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    @Override
5225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    public void onCreate(Bundle savedInstanceState) {
5325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        super.onCreate(savedInstanceState);
5425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
5525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        mSerialManager = (SerialManager)getSystemService(Context.SERIAL_SERVICE);
5625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        setContentView(R.layout.serial_chat);
5725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        mLog = (TextView)findViewById(R.id.log);
5825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        mEditText = (EditText)findViewById(R.id.message);
5925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        mEditText.setOnEditorActionListener(this);
6025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
6125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        if (false) {
6225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            mInputBuffer = ByteBuffer.allocateDirect(1024);
6325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            mOutputBuffer = ByteBuffer.allocateDirect(1024);
6425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        } else {
6525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            mInputBuffer = ByteBuffer.allocate(1024);
6625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            mOutputBuffer = ByteBuffer.allocate(1024);
6725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        }
6825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    }
6925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
7025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    @Override
7125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    public void onResume() {
7225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        super.onResume();
7325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
7425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        String[] ports = mSerialManager.getSerialPorts();
7525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        if (ports != null && ports.length > 0) {
7625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            try {
7725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mSerialPort = mSerialManager.openSerialPort(ports[0], 115200);
7825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                if (mSerialPort != null) {
7925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                    new Thread(this).start();
8025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                }
8125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            } catch (IOException e) {
8225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            }
8325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        }
8425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
8525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    }
8625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
8725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    @Override
8825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    public void onPause() {
8925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        super.onPause();
9025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
9125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    }
9225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
9325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    @Override
9425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    public void onDestroy() {
9525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        if (mSerialPort != null) {
9625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            try {
9725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mSerialPort.close();
9825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            } catch (IOException e) {
9925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            }
10025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            mSerialPort = null;
10125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        }
10225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        super.onDestroy();
10325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    }
10425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
10525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
10625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        if (/* actionId == EditorInfo.IME_ACTION_DONE && */ mSerialPort != null) {
10725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            try {
10825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                String text = v.getText().toString();
10925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Log.d(TAG, "write: " + text);
11025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                byte[] bytes = text.getBytes();
11125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mOutputBuffer.clear();
11225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mOutputBuffer.put(bytes);
11325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mSerialPort.write(mOutputBuffer, bytes.length);
11425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            } catch (IOException e) {
11525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Log.e(TAG, "write failed", e);
11625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            }
11725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            v.setText("");
11825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            return true;
11925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        }
12025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        Log.d(TAG, "onEditorAction " + actionId + " event: " + event);
12125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        return false;
12225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    }
12325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
12425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    public void run() {
12525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        Log.d(TAG, "run");
12625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        int ret = 0;
12725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        byte[] buffer = new byte[1024];
12825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        while (ret >= 0) {
12925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            try {
13025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Log.d(TAG, "calling read");
13125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mInputBuffer.clear();
13225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                ret = mSerialPort.read(mInputBuffer);
13325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Log.d(TAG, "read returned " + ret);
13425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mInputBuffer.get(buffer, 0, ret);
13525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            } catch (IOException e) {
13625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Log.e(TAG, "read failed", e);
13725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                break;
13825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            }
13925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
14025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            if (ret > 0) {
14125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Message m = Message.obtain(mHandler, MESSAGE_LOG);
14225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                String text = new String(buffer, 0, ret);
14325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                Log.d(TAG, "chat: " + text);
14425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                m.obj = text;
14525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                mHandler.sendMessage(m);
14625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            }
14725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        }
14825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        Log.d(TAG, "thread out");
14925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    }
15025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
15125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood   Handler mHandler = new Handler() {
15225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        @Override
15325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        public void handleMessage(Message msg) {
15425d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood            switch (msg.what) {
15525d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                case MESSAGE_LOG:
15625d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                    mLog.setText(mLog.getText() + (String)msg.obj);
15725d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood                    break;
15825d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood             }
15925d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood        }
16025d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood    };
16125d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood}
16225d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
16325d1fdc35767e84ba5f9ee352ae25f52f139a791Mike Lockwood
164