USB는 여러 종류의 장치를 지원한다. 이 다양한 장치를 기능별로 분류하여 class라고 부르고, class 별로 표준 protocol을 정의하여 놓았는데 각 장치는 이 protocol를 준수하여 동작하여야 한다.

USB Software stack은 다음과 같다.

 HID (Human Interface Device) - mouse, keyboard과 같은 저속 시리얼을 위한 Class
 CDC (Communication Device Class) - 시리얼 통신에 주로 이용
 MSC (Mass-Storage Class) - 대용량 저장 장치를 위한 것으로 USB Flash 같은 곳에 사용
 ACM (Abstract Control Model Class) - V-port와 같은 추상화된 구성에 주로 사용

이렇게 준비된 Class Driver를 사용하지 않고 사용자 정의 방식으로 동작이 가능하다.

의료 쪽의 PHCD (Personal Healthcare Device Class) 는 운동용 시계, 혈압 측정기, 체온계, 체중계, 혈당 측정기 등과 같은 의료 기기가 호스트에 접속하여 개인과 피트니스 코치 또는 환자와 의사 사이의 의사소통을 간편하게 하도록 지원한다.

USB는 master/slave라는 표현 대신 Host/Device라는 용어를 사용한다. Host가 Master에 해당되고, Device가 slave이다.
PC가 Host이고 Embedded Device가 Device로 동작할 때, 아래처럼 구성된다.

 

CDC (Communication Device Class)
 USB to Serial, USB to ethernet 등 USB 포트에 연결하여 통신하는 디바이스들이 CDC를 주로 사용한다. CDC는 통신 방법에 따라 ACM, ECM, EEM, NCM, OBEX 등등 다양한 subclass 들이 있다.

ACM (Abstract Control Model Class)
 USB to Serial 에 주로 사용되는 subclass 이다.

ECM (Ethernet Networking Control Model)
 USB to ethernet의 subclass 이다. ECM이 발표된 이후, ECM의 비효율적인 부분을 개선하여 발표되고 있다. EEM (Ethernet Emulation Model), NCM(Network Control Model), MBIM(Mobile Broadband Interface Model) 등은 모두 ethernet packet을 전송하기 위한 class 이다.

 

USB Host를 개발하려면 당연하게 USB Host Controller Driver가 있어야 한다. Host Controller는 OHCI, UHCI, EHCI and xHCI Controller가 있고, 이중 EHCI가 USB 2.0 high speed 까지 지원되는 것으로, 가장 널리 사용된다. 하지만, 대부분은 USB Device 개발이고, 이 경우엔 Host에서 돌아가는 class driver를 개발해야 하고 USB Device 에서 돌아가는 제어블럭이 필요하게 된다. 

 

출처: m.blog.naver.com/PostView.nhn?blogId=msnayana&logNo=220148672836&proxyReferer=https:%2F%2Fwww.google.com%2F

'USB' 카테고리의 다른 글

[USB] 호스트가 디바이스 정보 얻기  (0) 2021.01.17
[USB] Window USB Descriptor  (0) 2020.11.01

 

 USB 디바이스는 firmware 레벨에서 descriptor에 정보를 보관한다. 운영체제는 USB 디바이스와의 통신 채널인 control endpoint를 통해서 디바이스에 descriptor 제공을 요청하고, 요청을 받은 디바이스는 descriptor를 제공한다.

 USB Specification 2.0을 지원하려면 디바이스, 인터페이스, 엔드포인터에 대한 정보를 담고 있는 standard descriptor를 지원해야 한다. 디바이스는 제조사 별 class descriptor와 vendor-specific descriptor가 있다.

MS의 descriptorstandard USB string descriptor (OS string descriptor), OS feature descriptor가 있다. OS string Descriptor는 OS feature descriptor를 얻기 위해 필요한 Descriptor이다.

디바이스의 OS feature descriptor를 얻기 위해서 Windows는
 1. 디바이스의 OS string descriptor를 조회하기 위한 제어 요청을 디바이스에게 보낸다.
 2. 수신한 디바이스 OS string descriptor가 Microsoft가 정의한 포맷을 준수하는지 확인한다.
 3. 디바이스의 OS feature descriptor를 조회하기 위해서 OS string descriptor의 bMS_VendorCode 필드에 있는 데이터를 사용한다.

 

MS의 OS featrue descriptor 종류로는 Extened Compat ID, Extended Properties, Genre가 있다.
 - Extened Compat ID
 Windows에는 USB 디바이스의 기본 드라이버를 결정하기 위해서 calss 와 subclass 코드를 사용한다. 새로운 타입의 USB 디바이스는 이 class 와 subclass 코드를 가지고 있지 않다. 이런 경우에 USB 디바이스 제조사는 extended compat ID라는 OS featrue descriptor 정보를 디바이스 firmware에 저장한다. Windows는 디바이스가 연결될 때 이 정보를 조회하여 디바이스에 대한 기본 드라이버를 결정하고 load한다.
 - Extended Properties
 USB 디바이스의 class level 또는 devnod level를 선언할 수 있다. USB 디바이스 제조사는 이 Extended Properties OS feature descriptor를 이용해서 도움 페이지, URL, 아이콘 같은 추가 특성 정보를 펌웨어에 저장할 수 있다.
 - Genre
 이 디스크립터는 게임 컨드롤러 같은 HID 디바이스들이 상세한 configuration data를 제공하기 위해 사용한다. 예를 들어서 전형적인 게임 컨트롤러는 컨트롤에 대한 기본 정보를 포함하는 report descriptor를 가지고 있다. 하지만 이 데이터는 게임 컨트롤러가 사용될 수 있는 여러가지 다른 상황에서 컨트롤과 액션 간의 최적의 mapping을 하기에는 부족하다. USB 디바이스 제조사는 디바이스 펌웨어에 상세한 매핑 정보를 저장하게 위해 이 descriptor를 사용할 수 있다.

 

MS의 OS String Descriptor
USB 디바이스는 스트링 인덱스 0xEE에 저장된 OS String Descriptor를 갖고 있어야 한다.
 - 이 디스크립터를 사용한다는 것은 디바이스가 하나 이상의 OS feature descriptor를 갖고 있음을 의미
 - OS featrue descriptor 조회에 필요한 데이터들을 포함
 - USB 디바이스 제조사가 0xEE에 저장할 수 있는 스트링들로부터 OS String Descriptor를 구분할 수 있게 하는 signature를 포함
 - 버전 정보 포함

 

MS의 OS Feature Descriptor
버전 1.00 에서 MS는 3개의 OS feature descriptor에 대한 표준 포맷을 정의했다. OS feature descriptor는 다음 사항을 만족해야 한다.
 - 다비이스는 최대 255개까지 descriptor를 저장할 수 있다.
 - descriptor는 디바이스 또는 특정 인터페이스 기능과 연관된 것일 수 있다.
 - 각 타입 당 한개의 OS Feature Descriptor가 허용된다. 여러 OS Feature Descriptor들이 특정 인터페이스나 function에 연관될 수 있다. 이 경우에 디바이스는 자신이 갖고 있는 인터페이스들이나 function들 만큼의 디스크립터들을 가질 수 있다. 
 - descriptor는 크기와 버전정보를 포함해야 한다.
 - descriptor 최대 크기는 특정 OS featrue descriptor에 따라 다르다. 프로토콜은 feature descriptors 크기를 16MB까지 허용하지만, 그 크기는 펌웨어 비용 때문에 제한된다.

 

출처: blog.naver.com/jskimadd/10171305013

'USB' 카테고리의 다른 글

[USB] 호스트가 디바이스 정보 얻기  (0) 2021.01.17
[USB] USB 장치  (0) 2020.11.01

안드로이드 쉘에서 input 커맨드를 통해 텍스트 입력, 터치, 키 입력 등을 할 수 있다.

 

input text

input text “insert%syour%stext”

안드로이드에서 텍스트 입력을 하는 커맨드. %s 는 space를 의미한다. 안드로이드 쉘에서 다음과 같이 입력하면 된다.

(ex) input text “Hello%sWorld”

 

input tap

input tap [xPosition] [YPosition]

안드로이드에서 짧은 터치를 하는 커맨드. 안드로이드 디버깅 모드에 진입하면 터치하는 곳의 x좌표, y좌표를 알 수 있다. 이를 토대로 안드로이드 쉘에서 이 커맨드를 치면 해당하는 좌표를 짧게 클릭한다.

(ex) input tap 500 200

 

input swipe

input swipe fromXPosition fromYPosition toXPosition toYPosition Time

안드로이드에서 처음 좌표에서 끝 좌표까지 주어진 시간동안 터치를 재현해주는 커맨드이다. 예시의 경우 (100, 500) 부터 (100,1000) 까지 100ms 동안 터치를 해준다.

(ex) input swipe 100 500 100 1000 100

 

input keyevent

input keyevent #NUM

안드로이드에서 키보드 입력을 대신 할 수 있는 커맨드이다. 필자의 경우는 터치가 안되는 안드로이드 디바이스가 안드로이드 동작이 느려서 이 키 이벤트로 안드로이드를 제어했다. 성능이 낮은 디바이스의 경우 터치하는 것보다 키 이벤트로 입력하는 것이 더 빠르다.

(ex) input keyevent 4

 

 Keyevent List

  • 0 –> “KEYCODE_0”
  • 1 –> “KEYCODE_SOFT_LEFT”
  • 2 –> “KEYCODE_SOFT_RIGHT”
  • 3 –> “KEYCODE_HOME”
  • 4 –> “KEYCODE_BACK”
  • 5 –> “KEYCODE_CALL”
  • 6 –> “KEYCODE_ENDCALL”
  • 7 –> “KEYCODE_0”
  • 8 –> “KEYCODE_1”
  • 9 –> “KEYCODE_2”
  • 10 –> “KEYCODE_3”
  • 11 –> “KEYCODE_4”
  • 12 –> “KEYCODE_5”
  • 13 –> “KEYCODE_6”
  • 14 –> “KEYCODE_7”
  • 15 –> “KEYCODE_8”
  • 16 –> “KEYCODE_9”
  • 17 –> “KEYCODE_STAR”
  • 18 –> “KEYCODE_POUND”
  • 19 –> “KEYCODE_DPAD_UP”
  • 20 –> “KEYCODE_DPAD_DOWN”
  • 21 –> “KEYCODE_DPAD_LEFT”
  • 22 –> “KEYCODE_DPAD_RIGHT”
  • 23 –> “KEYCODE_DPAD_CENTER”
  • 24 –> “KEYCODE_VOLUME_UP”
  • 25 –> “KEYCODE_VOLUME_DOWN”
  • 26 –> “KEYCODE_POWER”
  • 27 –> “KEYCODE_CAMERA”
  • 28 –> “KEYCODE_CLEAR”
  • 29 –> “KEYCODE_A”
  • 30 –> “KEYCODE_B”
  • 31 –> “KEYCODE_C”
  • 32 –> “KEYCODE_D”
  • 33 –> “KEYCODE_E”
  • 34 –> “KEYCODE_F”
  • 35 –> “KEYCODE_G”
  • 36 –> “KEYCODE_H”
  • 37 –> “KEYCODE_I”
  • 38 –> “KEYCODE_J”
  • 39 –> “KEYCODE_K”
  • 40 –> “KEYCODE_L”
  • 41 –> “KEYCODE_M”
  • 42 –> “KEYCODE_N”
  • 43 –> “KEYCODE_O”
  • 44 –> “KEYCODE_P”
  • 45 –> “KEYCODE_Q”
  • 46 –> “KEYCODE_R”
  • 47 –> “KEYCODE_S”
  • 48 –> “KEYCODE_T”
  • 49 –> “KEYCODE_U”
  • 50 –> “KEYCODE_V”
  • 51 –> “KEYCODE_W”
  • 52 –> “KEYCODE_X”
  • 53 –> “KEYCODE_Y”
  • 54 –> “KEYCODE_Z”
  • 55 –> “KEYCODE_COMMA”
  • 56 –> “KEYCODE_PERIOD”
  • 57 –> “KEYCODE_ALT_LEFT”
  • 58 –> “KEYCODE_ALT_RIGHT”
  • 59 –> “KEYCODE_SHIFT_LEFT”
  • 60 –> “KEYCODE_SHIFT_RIGHT”
  • 61 –> “KEYCODE_TAB”
  • 62 –> “KEYCODE_SPACE”
  • 63 –> “KEYCODE_SYM”
  • 64 –> “KEYCODE_EXPLORER”
  • 65 –> “KEYCODE_ENVELOPE”
  • 66 –> “KEYCODE_ENTER”
  • 67 –> “KEYCODE_DEL”
  • 68 –> “KEYCODE_GRAVE”
  • 69 –> “KEYCODE_MINUS”
  • 70 –> “KEYCODE_EQUALS”
  • 71 –> “KEYCODE_LEFT_BRACKET”
  • 72 –> “KEYCODE_RIGHT_BRACKET”
  • 73 –> “KEYCODE_BACKSLASH”
  • 74 –> “KEYCODE_SEMICOLON”
  • 75 –> “KEYCODE_APOSTROPHE”
  • 76 –> “KEYCODE_SLASH”
  • 77 –> “KEYCODE_AT”
  • 78 –> “KEYCODE_NUM”
  • 79 –> “KEYCODE_HEADSETHOOK”
  • 80 –> “KEYCODE_FOCUS”
  • 81 –> “KEYCODE_PLUS”
  • 82 –> “KEYCODE_MENU” //MK: 비번이 걸려 있지 않은 경우, 화면을 켠상태에서 해당 Keycode를 입력하면 메인 화면으로 넘어감
  • 83 –> “KEYCODE_NOTIFICATION”
  • 84 –> “KEYCODE_SEARCH”
  • 85 –> “KEYCODE_MEDIA_PLAY_PAUSE”
  • 86 –> “KEYCODE_MEDIA_STOP”
  • 87 –> “KEYCODE_MEDIA_NEXT”
  • 88 –> “KEYCODE_MEDIA_PREVIOUS”
  • 89 –> “KEYCODE_MEDIA_REWIND”
  • 90 –> “KEYCODE_MEDIA_FAST_FORWARD”
  • 91 –> “KEYCODE_MUTE”
  • 92 –> “KEYCODE_PAGE_UP”
  • 93 –> “KEYCODE_PAGE_DOWN”
  • 94 –> “KEYCODE_PICTSYMBOLS”
  • 224 –> “KEYCODE_WAKEUP” //MK: Power 버튼과 차이가 있음. 화면이 켜져 있는 상태에서 해당 키를 입력하면 화면이 그대로 켜져있음

 

 

출처

https://mkblog.co.kr/2018/09/10/android-adb-input-command/

 

[Android] ADB “input” Command 사용법 (adb shell input) – MKBlog

안드로이드 단말에서 Developer 옵션을 켜면 ADB를 사용해서 많은 것을 할 수 있다. 나의 경우 게임에서 특정 플레이를 반복적으로 해야 하는 부분을 자동으로 해보려고 찾다가 “adb shell input” Command로 구현 할 수 있어서 관련 Command를 정리하였다. Input Text Command: adb shell input text “insert%syour%stext” (%s 는 space를 의미) 설명: “insert text” C

mkblog.co.kr

 

'Android' 카테고리의 다른 글

에러 코드 <include/errno.h>  (0) 2019.04.09

Android에서 tinyalsa를 다루면서 pcm_read 에러가 나길래 찾아본 에러 코드..

ALSA 다루다가 에러 났을 때 에러 코드에 따른 대응 방법은 ALSA; Advanced Linux Sound Architecture 글 참고

<참고 웹페이지> https://android.googlesource.com/kernel/lk/+/dima/for-travis/include/errno.h

 

/*
 * Copyright (c) 2013 Corey Tabaka
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __ERRNO_H
#define __ERRNO_H
#include <compiler.h>
__BEGIN_CDECLS
extern int *__geterrno(void);
#define errno (*__geterrno())
#define	EPERM 1		/* Not super-user */
#define	ENOENT 2	/* No such file or directory */
#define	ESRCH 3		/* No such process */
#define	EINTR 4		/* Interrupted system call */
#define	EIO 5		/* I/O error */
#define	ENXIO 6		/* No such device or address */
#define	E2BIG 7		/* Arg list too long */
#define	ENOEXEC 8	/* Exec format error */
#define	EBADF 9		/* Bad file number */
#define	ECHILD 10	/* No children */
#define	EAGAIN 11	/* No more processes */
#define	ENOMEM 12	/* Not enough core */
#define	EACCES 13	/* Permission denied */
#define	EFAULT 14	/* Bad address */
#define	ENOTBLK 15	/* Block device required */
#define	EBUSY 16	/* Mount device busy */
#define	EEXIST 17	/* File exists */
#define	EXDEV 18	/* Cross-device link */
#define	ENODEV 19	/* No such device */
#define	ENOTDIR 20	/* Not a directory */
#define	EISDIR 21	/* Is a directory */
#define	EINVAL 22	/* Invalid argument */
#define	ENFILE 23	/* Too many open files in system */
#define	EMFILE 24	/* Too many open files */
#define	ENOTTY 25	/* Not a typewriter */
#define	ETXTBSY 26	/* Text file busy */
#define	EFBIG 27	/* File too large */
#define	ENOSPC 28	/* No space left on device */
#define	ESPIPE 29	/* Illegal seek */
#define	EROFS 30	/* Read only file system */
#define	EMLINK 31	/* Too many links */
#define	EPIPE 32	/* Broken pipe */
#define	EDOM 33		/* Math arg out of domain of func */
#define	ERANGE 34	/* Math result not representable */
#define	ENOMSG 35	/* No message of desired type */
#define	EIDRM 36	/* Identifier removed */
#define	ECHRNG 37	/* Channel number out of range */
#define	EL2NSYNC 38	/* Level 2 not synchronized */
#define	EL3HLT 39	/* Level 3 halted */
#define	EL3RST 40	/* Level 3 reset */
#define	ELNRNG 41	/* Link number out of range */
#define	EUNATCH 42	/* Protocol driver not attached */
#define	ENOCSI 43	/* No CSI structure available */
#define	EL2HLT 44	/* Level 2 halted */
#define	EDEADLK 45	/* Deadlock condition */
#define	ENOLCK 46	/* No record locks available */
#define EBADE 50	/* Invalid exchange */
#define EBADR 51	/* Invalid request descriptor */
#define EXFULL 52	/* Exchange full */
#define ENOANO 53	/* No anode */
#define EBADRQC 54	/* Invalid request code */
#define EBADSLT 55	/* Invalid slot */
#define EDEADLOCK 56	/* File locking deadlock error */
#define EBFONT 57	/* Bad font file fmt */
#define ENOSTR 60	/* Device not a stream */
#define ENODATA 61	/* No data (for no delay io) */
#define ETIME 62	/* Timer expired */
#define ENOSR 63	/* Out of streams resources */
#define ENONET 64	/* Machine is not on the network */
#define ENOPKG 65	/* Package not installed */
#define EREMOTE 66	/* The object is remote */
#define ENOLINK 67	/* The link has been severed */
#define EADV 68		/* Advertise error */
#define ESRMNT 69	/* Srmount error */
#define	ECOMM 70	/* Communication error on send */
#define EPROTO 71	/* Protocol error */
#define	EMULTIHOP 74	/* Multihop attempted */
#define	ELBIN 75	/* Inode is remote (not really error) */
#define	EDOTDOT 76	/* Cross mount point (not really error) */
#define EBADMSG 77	/* Trying to read unreadable message */
#define EFTYPE 79	/* Inappropriate file type or format */
#define ENOTUNIQ 80	/* Given log. name not unique */
#define EBADFD 81	/* f.d. invalid for this operation */
#define EREMCHG 82	/* Remote address changed */
#define ELIBACC 83	/* Can't access a needed shared lib */
#define ELIBBAD 84	/* Accessing a corrupted shared lib */
#define ELIBSCN 85	/* .lib section in a.out corrupted */
#define ELIBMAX 86	/* Attempting to link in too many libs */
#define ELIBEXEC 87	/* Attempting to exec a shared library */
#define ENOSYS 88	/* Function not implemented */
#define ENMFILE 89      /* No more files */
#define ENOTEMPTY 90	/* Directory not empty */
#define ENAMETOOLONG 91	/* File or path name too long */
#define ELOOP 92	/* Too many symbolic links */
#define EOPNOTSUPP 95	/* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define ECONNRESET 104  /* Connection reset by peer */
#define ENOBUFS 105	/* No buffer space available */
#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
#define EPROTOTYPE 107	/* Protocol wrong type for socket */
#define ENOTSOCK 108	/* Socket operation on non-socket */
#define ENOPROTOOPT 109	/* Protocol not available */
#define ESHUTDOWN 110	/* Can't send after socket shutdown */
#define ECONNREFUSED 111	/* Connection refused */
#define EADDRINUSE 112		/* Address already in use */
#define ECONNABORTED 113	/* Connection aborted */
#define ENETUNREACH 114		/* Network is unreachable */
#define ENETDOWN 115		/* Network interface is not configured */
#define ETIMEDOUT 116		/* Connection timed out */
#define EHOSTDOWN 117		/* Host is down */
#define EHOSTUNREACH 118	/* Host is unreachable */
#define EINPROGRESS 119		/* Connection already in progress */
#define EALREADY 120		/* Socket already connected */
#define EDESTADDRREQ 121	/* Destination address required */
#define EMSGSIZE 122		/* Message too long */
#define EPROTONOSUPPORT 123	/* Unknown protocol */
#define ESOCKTNOSUPPORT 124	/* Socket type not supported */
#define EADDRNOTAVAIL 125	/* Address not available */
#define ENETRESET 126
#define EISCONN 127		/* Socket is already connected */
#define ENOTCONN 128		/* Socket is not connected */
#define ETOOMANYREFS 129
#define EPROCLIM 130
#define EUSERS 131
#define EDQUOT 132
#define ESTALE 133
#define ENOTSUP 134		/* Not supported */
#define ENOMEDIUM 135   /* No medium (in tape drive) */
#define ENOSHARE 136    /* No such host or network path */
#define ECASECLASH 137  /* Filename exists with different case */
#define EILSEQ 138
#define EOVERFLOW 139	/* Value too large for defined data type */
#define EWOULDBLOCK EAGAIN	/* Operation would block */
#define __ELASTERROR 2000	/* Users can add values starting here */
__END_CDECLS
#endif

'Android' 카테고리의 다른 글

[안드로이드] input 커맨드  (0) 2019.05.28

ALSA는 Audio Linux Sound Architecture의 약자.

리눅스에서 Audio를 구현하고자 할 때 사용되는 공개 라이브러리이다.

많이 사용되는 ALSA와 ALSA보다 몸집이 작은 tinyALSA, 이 두 라이브러리의 기본 API에 대해 설명한다.

 

 

  • ALSA Overview
  • tinyALSA

    • Data Structure

      • PCM config
      • PCM Structure
    • PCM Open
    • PCM Read
    • PCM Write
    • PCM Close
  • ALSA
    • Data Structures
    • PCM Open
    • PCM HW Params
    • PCM SW Params
    • PCM Prepare
    • PCM Start
    • PCM Avail
    • PCM Read
    • PCM Write
    • PCM Close
  • ALSA lib 참고 웹페이지

    • ALSA
    • Tiny ALSA

 

 


ALSA Overview

 

흔히 말하는 ALSA는 보통 User Space에서 ALSA library를 가져다 쓰는 것을 말한다.

ALSA application으로는 aplay, arecode, amixer, tinyplay 등이 있으며, 오디오 어플리케이션을 쓸 때 이 코드를 많이 참고하여 사용한다.


 

 

 

tinyALSA

Android에는 tinyALSA가 올라가있다.

tinyALSA의 경우에는 단순히 Open, Read/Write, Close만 해주면 audio 사용이 가능하다.

 

 

Data Structure

tinyALSA를 사용하기 위해서는 PCM Handler와 PCM Config가 필요하다.

 

PCM config

struct pcm_config {
    unsigned int channels;
    unsigned int rate;
    unsigned int period_size;
    unsigned int period_count;
    enum pcm_format format;
    /* Values to use for the ALSA start, stop and silence thresholds.  Setting
     * any one of these values to 0 will cause the default tinyalsa values to be
     * used instead.  Tinyalsa defaults are as follows.
     *
     * start_threshold   : period_count * period_size
     * stop_threshold    : period_count * period_size
     * silence_threshold : 0
     */
    unsigned int start_threshold;
    unsigned int stop_threshold;
    unsigned int silence_threshold;
    /* Minimum number of frames available before pcm_mmap_write() will actually
     * write into the kernel buffer. Only used if the stream is opened in mmap mode
     * (pcm_open() called with PCM_MMAP flag set).   Use 0 for default.
     */
    int avail_min;
};

pcm config 구조체에서는 channel 개수, rate, period size, period count, audio format에 대한 설정을 해준다.

  • format
    • PCM_FORMAT_S16_LE
      • Signed 16-bit, Little Endian
    • 그 외 PCM_FORMAT_S16_BE, PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE
    • tinyalsa\pcm.h 에서 확인 가능
  • period size
    • 한번에 읽어오는 frame의 개수
  • period count
    • buffer = period size * period count
  • start threshold
    • PCM start 하기에 최소한으로 필요한 frame 개수
  • stop threshold
    • PCM stop 하기에 최소한으로 필요한 frame 개수

 

PCM Structure

pcm 구조체

struct pcm {
    int fd;
    unsigned int flags;
    int running:1;
    int underruns;
    unsigned int buffer_size;
    unsigned int boundary;
    char error[PCM_ERROR_MAX];
    struct pcm_config config;
    struct snd_pcm_mmap_status *mmap_status;
    struct snd_pcm_mmap_control *mmap_control;
    struct snd_pcm_sync_ptr *sync_ptr;
    void *mmap_buffer;
    unsigned int noirq_frames_per_msec;
    int wait_for_avail_min;
};

 

PCM Open

struct pcm *pcm_open(unsigned int card, unsigned int device, unsigned int flags, const struct pcm_config *config)

Description

pcm open을 하고 pcm 구조체를 받아온다.

Parameters

card - sound card 번호

device - dai-link 번호

ex) device tree에서 sound card 0의 dai-link 0번 i2S를 사용한다면, card와 device에 각각 0을 넘겨주면 된다.

flags - pcm open flags

ex) PCM_OUT, PCM_IN, PCM_MMAP, PCM_NOIRQ, PCM_NORESTART, PCM_MONOTONIC, PCM_NONBLOCK, PCM_STATE_PREPARED .. etc

config - pcm config 구조체

Return

pcm 구조체

 

PCM Read

int pcm_read(struct pcm *pcm, void *data, unsigned int count)

Description

data에 pcm read한 데이터를 count만큼 가져온다.

Parameters

pcm - open할 때 반환받은 pcm 구조체

data - audio data를 저장할 buffer

count - frame 당 byte 개수

보통 하나의 frame에 몇 byte가 있는지 반환하는 pcm_frames_to_bytes(const struct pcm *pcm, unsigned int frames) 함수를 사용해서 count 값을 넣어준다.

Returns

0일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환

 

PCM Write

int pcm_write(struct pcm *pcm, const void *data, unsigned int count)

Description

data에 저장된 데이터를 count만큼 쓴다.

Parameters

pcm - open할 때 반환받은 pcm 구조체

data - audio data를 저장된 buffer

count - frame 당 byte 개수

보통 하나의 frame에 몇 byte가 있는지 반환하는 pcm_frames_to_bytes(const struct pcm *pcm, unsigned int frames) 함수를 사용해서 count 값을 넣어준다.

Returns

0 일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환


PCM Close

int pcm_close(struct pcm *pcm)

Description

pcm을 close한다.

Parameters

pcm - open할 때 반환받은 pcm 구조체

Returns

항상 0 반환

 

 

 

 

 

 

ALSA

Linux에서는 ALSA를 사용한다.

ALSA의 경우에는 open, hw parameter 설정, sw parameter 설정, prepare, start, (avail 체크), read/write, close 과정으로 audio를 다룬다.

 

 

Data Structures

PCM structure

typedef struct  _snd_pcm snd_pcm_t

PCM HW config

typedef struct  _snd_pcm_hw_params snd_pcm_hw_params_t

PCM SW config

typedef struct  _snd_pcm_sw_params snd_pcm_sw_params_t

 

PCM Open

int snd_pcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode)

Description

pcm을 open한다.

Parameters

pcmp - open할 때 반환 받을 pcm 구조체

name - PCM 식별자

(ex) "hw:0,2"

stream - playback 목적으로 pcm open을 하는지, capture 목적으로 pcm open을 하는지 넘겨줌

(ex) SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE

mode - open mode

(ex) SND_PCM_NONBLOCK, SND_PCM_ASYNC

Returns

항상 0 반환

 

PCM HW Params

Hardware Parameter란 audio format, channel 개수, sampling rate, period size, buffer size 등을 말한다.

 

ALSA Library FunctionDescription

snd_pcm_hw_params_malloc snd_pcm_hw_params_t 구조체 메모리 할당
snd_pcm_hw_params_any snd_pcm_hw_params_t 구조체 초기화
snd_pcm_hw_params_set_access access type 설정 (ex) SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_ACCESS_RW_NONINTERLEAVED
snd_pcm_hw_params_set_format audio format 설정 (ex) SND_PCM_FORMAT_S16_LE
snd_pcm_hw_params_set_channels audio channel 설정
snd_pcm_hw_params_set_buffer_size audio buffer size 설정
snd_pcm_hw_params_set_rate_near 샘플레이트 설정 시 하드웨어가 정확한 샘플레이트를 지원하지 않는다면 가장 근접한 가능한 레이트를 사용하도록 설정
snd_pcm_hw_params_set_period_size alsa period_size를 설정
snd_pcm_hw_params

snd_pcm_hw_params_t 구조체에 저장된 PCM hardware configuration을 하드웨어에 알려주고 snd_pcm_prepare를 호출

snd_pcm_hw_params_free snd_pcm_hw_params_t 구조체 free


참고 웹페이지  https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___h_w___params.html#ga6e2dd8efbb7a4084bd05e6cc458d84f7

 

 

 

<cf> interleaved access vs non-interleaved access

 

  • Interleaved mode
    • 하나의 buffer에 channel sample이 번갈아가며 저장
  • Non-interleaved mode
    • 각 채널별로 buffer가 존재하여 sample이 저장됨

 

 

 

PCM SW Params

Software Parameter란 start threshold, stop threshold, avail min 등을 말한다.

 

ALSA Library FunctionDescription

snd_pcm_sw_params_malloc snd_pcm_sw_params_t 구조체 할당
snd_pcm_sw_params_current 현재 SW config를 snd_pcm_sw_params_t 구조체에 저장
snd_pcm_sw_params_set_start_threshold start threshold 설정 (보통 period size로 설정) ※ byte 크기로 넘겨주는 것에 유의
snd_pcm_sw_params_set_avail_min 최소 avail 설정 (보통 period size으로 설정)
snd_pcm_sw_params snd_pcm_sw_params_t 구조체에 저장된 PCM software configuration을 아래 layer에 알려줌
snd_pcm_sw_params_free snd_pcm_sw_params_t 구조체 free

참고 웹페이지 https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___s_w___params.html

 

(cf) alsa에서 말하는 avail 이란, buffer에서 빈 공간 frame 개수를 말한다. delay는 buffer에 있는 데이터가 들은 frame 개수를 말한다.

 

PCM Prepare

int snd_pcm_prepare(snd_pcm_t *pcm)

Description

pcm을 prepare한다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

0 일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환


PCM Start

int snd_pcm_start(snd_pcm_t *pcm)

Description

pcm을 start한다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

0 일 경우, 성공

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환


PCM Avail

snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm)

Description

읽히거나 쓸 준비가 된 frame 개수를 반환한다. (ALSA에서 보통 avail은 버퍼의 비어있는 공간, delay는 버퍼의 데이터가 있는 공간을 말한다.)

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

양수일 경우, frame 개수 반환

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

-EBADFD의 경우, 어플리케이션과 alsa-lib 사이에 연결이 끊어진 경우에 반환

-ENOTTY, -ENODEV 의 경우, device가 물리적으로 해제된 경우에 반환

 

PCM Read

snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

interleaved frame을 읽는다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 찰 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함.

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함.

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능

snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

non-interleaved frame을 읽는다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 찰 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이나 overrun 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함.

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함.

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능

PCM Write

snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

interleaved frame을 쓴다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 play 될때까지 기다리거나 playback ring buffer에 넣을 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능

 

snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void buffer, snd_pcm_uframes_t size)

Description

non-interleaved frame을 쓴다.

만일 PCM이 blocking mode로 열렸을 경우, 모든 frame이 play 될때까지 기다리거나 playback ring buffer에 넣을 때까지 기다린다. underrun이 발생할 경우에만 읽어온 frame 개수가 적을 수 있다.

non-blocking mode일 경우, 기다리지 않는다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

buffer - 읽어오려는 frame을 담을 버퍼

size - 읽으려는 frame 개수

Returns

양수일 경우, 읽어온 frame 개수 반환

-EPIPE의 경우, underrun이 발생할 때 반환

underrun이 발생 하는 경우, snd_pcm_prepare를 호출해야 함

-ESTRPIPE 의 경우, device가 suspend 상태일 때 반환

suspend 상태인 경우, snd_pcm_resume을 해준 뒤 snd_pcm_prepare 호출해야 함

-EBADFD의 경우, 올바른 state가 아닐 경우 반환

SND_PCM_STATE_PREPARED 상태나 SND_PCM_STATE_RUNNING 상태일 때만 read/write가 가능


PCM Close

int snd_pcm_close(snd_pcm_t *pcm)

Description

pcm을 close한다.

Parameters

pcm - open할 때 반환 받은 pcm 구조체

Returns

0 일 경우, 성공

음수의 경우 실패

 

 

 

ALSA library 참고 웹페이지

ALSA

ALSA libWeb Page

PCM interface https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#ga042aba7262a4cbb4d444b6fc08cb7124
HW params https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___h_w___params.html
SW Params https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___s_w___params.html#ga79b12cbbd309750156261e7f5a39167b

 

Tiny ALSA

ALSA libWeb Page

github https://github.com/tinyalsa/tinyalsa

 

 

+ Recent posts