2012년 1월 16일 월요일

linux cp2104 driver

CP2104 USB to Serial를 사용하는데 ubuntu에서 minicom이 안되는 문제가 있다.

찾아 보니 CP210x driver에 baudrate 초기화 버그가 있는 듯...

http://www.spinics.net/lists/linux-usb/msg56969.html

그래서 driver patch를 적용하여 보겠습니다.

자신이 사용하는 kernel 버전을 확인한다.

커널 버전 확인
$uname -a
Linux codewalker-desktop 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:12:07 UTC 2012 x86_64 GNU/Linux


synaptic에서 desktop kernel source를 받는다.

linux-source, linux-source-2.6.32

아래 path로 소스 파일이 받아 진다.

/usr/src/linux-source-2.6.32.tar.bz2

/usr/src/linux-source-2.6.32/drivers/usb/serial/cp210x.c 수정한다.

 diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 3835106..dcba930 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -201,6 +201,8 @@ static struct usb_serial_driver cp210x_device = {
 #define CP210X_EMBED_EVENTS 0x15
 #define CP210X_GET_EVENTSTATE 0x16
 #define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1d
+#define CP210X_SET_BAUDRATE 0x1e
 
 /* CP210X_IFC_ENABLE */
 #define UART_ENABLE  0x0001
@@ -459,16 +461,12 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
  unsigned int *cflagp, unsigned int *baudp)
 {
  unsigned int cflag, modem_ctl[4];
- unsigned int baud;
+ u32 baud;
  unsigned int bits;
 
  dbg("%s - port %d", __func__, port->number);
 
- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
-  baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
-
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, sizeof(baud));
  dbg("%s - baud rate = %d", __func__, baud);
  *baudp = baud;
 
@@ -580,7 +578,8 @@ static void cp210x_set_termios(struct tty_struct *tty,
   struct usb_serial_port *port, struct ktermios *old_termios)
 {
  unsigned int cflag, old_cflag;
- unsigned int baud = 0, bits;
+ u32 baud;
+ unsigned int bits;
  unsigned int modem_ctl[4];
 
  dbg("%s - port %d", __func__, port->number);
@@ -595,8 +594,8 @@ static void cp210x_set_termios(struct tty_struct *tty,
  /* If the baud rate is to be updated*/
  if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
   dbg("%s - Setting baud rate to %d baud", __func__, baud);
-  if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
-     ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
+  if (cp210x_set_config(port, CP210X_SET_BAUDRATE,
+       &baud, sizeof(baud))) {
    dbg("Baud rate requested not supported by device");
    baud = tty_termios_baud_rate(old_termios);
   }
-- 
 

$sudo make menuconfig


$sudo make -j10


kernel 빌드 시 에러가 발생 아래와 같이 수정.


ERROR-2
LD [M]  ubuntu/omnibook/omnibook.o
ld: /ubuntu/omnibook/sections.lds: No such file: No such file or directory
make[2]: *** [ubuntu/omnibook/omnibook.o] Error 1
make[1]: *** [ubuntu/omnibook] Error 2
make: *** [ubuntu] Error 2
SOLUTION-2
$ sudo vi /usr/src/linux/ubuntu/omnibook/Makefile
160: #EXTRA_LDFLAGS +=  $(src)/sections.lds
161: EXTRA_LDFLAGS += $(PWD)/ubuntu/omnibook/sections.lds


http://thangamaniarun.wordpress.com/2010/07/08/how-to-quickly-build-custom-kernel-on-ubuntu-10-04/




cp210x.ko module 만들기


$sudo make modules


$sudo make modules_install



[/lib/modules]$ ls -l
합계 20
drwxr-xr-x 4 root root 4096 2010-04-29 21:45 2.6.32-21-generic
drwxr-xr-x 5 root root 4096 2011-12-16 18:47 2.6.32-36-generic
drwxr-xr-x 5 root root 4096 2012-01-17 16:24 2.6.32-37-generic
drwxr-xr-x 5 root root 4096 2012-01-24 17:09 2.6.32-38-generic
drwxr-xr-x 3 root root 4096 2012-01-25 17:54 2.6.32.52+drm33.21



kernel 소스 Makefile에 EXTRAVERSION이 실제 설치된 kernel과 틀리다.


그래서 수동으로 cp210x.ko를 2.6.32-38-generic 폴더 밑에 파일로 바꿔주면 된다.


EXTRAVERSION이 다르지만 insmod나 hot-plugin시 문제 없이 module이 올라 간다.


혹시나 드라이버에 문제가 생기면 동일한 linux-image-generic를 synaptic에서 재설치해 주면 해결된다.


module의 EXTRAVERSION을 확인하기 위해서는 modinfo를 이용하면 된다.



alias:          usb:v0FCFp1004d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0FCFp1003d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BEDp1101d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BEDp1100d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v08FDp000Ad*dc*dsc*dp*ic*isc*ip*
alias:          usb:v08E6p5501d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0745p1000d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0489pE000d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0471p066Ad*dc*dsc*dp*ic*isc*ip*
alias:          usb:v045Bp0053d*dc*dsc*dp*ic*isc*ip*
depends:        usbserial
vermagic:       2.6.32.52+drm33.21 SMP mod_unload modversions 
parm:           debug:Enable verbose debugging messages (bool)
[/lib/modules/2.6.32-38-generic/kernel/drivers/usb/serial]$