iT邦幫忙

DAY 28
0

x86 android 設備與外部硬體溝通研究系列 第 28

x86 android 設備與外部硬體溝通研究 - cdc-acm.c (28/30)

  • 分享至 

  • twitterImage
  •  

今天從 CDC serial driver 的 setParameters 部分下手,

        private static final int SET_LINE_CODING = 0x20;  // USB CDC 1.1 section 6.2
  private static final int USB_RECIP_INTERFACE = 0x01;
        private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
        // UsbConstants.USB_TYPE_CLASS = 0x20

        @Override
        public void setParameters(int baudRate, int dataBits, int stopBits, int parity) {
            byte stopBitsByte;
            switch (stopBits) {
                case STOPBITS_1: stopBitsByte = 0; break;
                case STOPBITS_1_5: stopBitsByte = 1; break;
                case STOPBITS_2: stopBitsByte = 2; break;
                default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits);
            }

            byte parityBitesByte;
            switch (parity) {
                case PARITY_NONE: parityBitesByte = 0; break;
                case PARITY_ODD: parityBitesByte = 1; break;
                case PARITY_EVEN: parityBitesByte = 2; break;
                case PARITY_MARK: parityBitesByte = 3; break;
                case PARITY_SPACE: parityBitesByte = 4; break;
                default: throw new IllegalArgumentException("Bad value for parity: " + parity);
            }

            byte[] msg = {
                    (byte) ( baudRate & 0xff),
                    (byte) ((baudRate >> 8 ) & 0xff),
                    (byte) ((baudRate >> 16) & 0xff),
                    (byte) ((baudRate >> 24) & 0xff),
                    stopBitsByte,
                    parityBitesByte,
                    (byte) dataBits}; // 共計 7 byte 的msg資料
            sendAcmControlMessage(SET_LINE_CODING, 0, msg);
        }

    private int sendAcmControlMessage(int request, int value, byte[] buf) {
            return mConnection.controlTransfer(
                    USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000);
        }

上面是 CDC serial driver 的控制方式

下面是 Linux/drivers/usb/class/cdc-acm.c 針對 CDC 通訊控制中設定 serial port 參數的部分,我們先來看看有什麼不一樣 :

 static void acm_tty_set_termios(struct tty_struct *tty,
                                                 struct ktermios *termios_old)
 {
         struct acm *acm = tty->driver_data;
         struct ktermios *termios = &tty->termios;
         struct usb_cdc_line_coding newline;
         int newctrl = acm->ctrlout;
 
         newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); // 轉換成 little endian binary (32bit)
         newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
         newline.bParityType = termios->c_cflag & PARENB ?
                                 (termios->c_cflag & PARODD ? 1 : 2) +
                                 (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
         switch (termios->c_cflag & CSIZE) {
         case CS5:
                 newline.bDataBits = 5;
                 break;
         case CS6:
                 newline.bDataBits = 6;
                 break;
         case CS7:
                 newline.bDataBits = 7;
                 break;
         case CS8:
         default:
                 newline.bDataBits = 8;
                 break;
         }
         /* FIXME: Needs to clear unsupported bits in the termios */
         acm->clocal = ((termios->c_cflag & CLOCAL) != 0);

         //這邊用到的 #define ACM_CTRL_DTR            0x01 
         if (!newline.dwDTERate) {
                 newline.dwDTERate = acm->line.dwDTERate;
                 newctrl &= ~ACM_CTRL_DTR; // ACM_CTRL_DTR 變成 0xFE 跟 newctrl 做 AND 運算
         } else
                 newctrl |=  ACM_CTRL_DTR; // 跟 newctrl 做 OR 運算
 
         if (newctrl != acm->ctrlout)
                 acm_set_control(acm, acm->ctrlout = newctrl);
 
         if (memcmp(&acm->line, &newline, sizeof newline)) {
                 memcpy(&acm->line, &newline, sizeof newline);
                 dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n",
                         __func__,
                         le32_to_cpu(newline.dwDTERate),
                         newline.bCharFormat, newline.bParityType,
                         newline.bDataBits);
                 acm_set_line(acm, &acm->line);
         }
 }

由上面可以看到他最後是交由

acm_set_control acm_set_line

送出控制指令,而上述這兩的 method 又全部把資料交到 acm_ctrl_msg( ) 這個 method 做分配。

而上述兩者 跟 acm_ctrl_msg 之間又做了那些動作呢? 我們留著明天在作進一步說明

我們明天見 :P

Ref :

http://lxr.free-electrons.com/source/drivers/usb/class/cdc-acm.c

http://lxr.free-electrons.com/source/drivers/usb/class/cdc-acm.h#L34

http://lxr.free-electrons.com/source/drivers/usb/core/message.c#L80

http://lxr.free-electrons.com/source/include/linux/usb.h#L1791

結語:

有沒有發現

                    (byte) ( baudRate & 0xff),
                    (byte) ((baudRate >> 8 ) & 0xff),
                    (byte) ((baudRate >> 16) & 0xff),
                    (byte) ((baudRate >> 24) & 0xff),

         newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); // 轉換成 little endian binary (32bit)

兩個好像結果不太一樣? 似乎可以從這邊下手研究兩者異同之處 :P


上一篇
x86 android 設備與外部硬體溝通研究 - (27/30)
下一篇
x86 android 設備與外部硬體溝通研究 - cdc-acm.c (29/30)
系列文
x86 android 設備與外部硬體溝通研究30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言