HGLAN $B$H(B LAN $B$H$N:9J,(B
LAN/source_CD/linux-2.4.17_mvl21-sandpoint$B$@$1$KH/8+(B: .hhl_target_lspname
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/Makefile LAN/source_CD/linux-2.4.17_mvl21-sandpoint/Makefile
*** HGLAN/source_CD/linux-2.4.17_mvl21/Makefile 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/Makefile 2004-05-24 17:35:29.000000000 +0900
***************
*** 101,107 ****
# echo -n "`hhl-whereami`/../../devkit/`cat .hhl_target_installdir`/target"; \
# fi)
! INSTALL_MOD_PATH := /home/martin/linux-2.4.17_mvl21/modules
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
--- 101,107 ----
# echo -n "`hhl-whereami`/../../devkit/`cat .hhl_target_installdir`/target"; \
# fi)
! INSTALL_MOD_PATH := /home/martin/linux_mvl21-sandpoint/modules
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/boot/common/misc-simple.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/boot/common/misc-simple.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/boot/common/misc-simple.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/boot/common/misc-simple.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 35,47 ****
#ifdef FLASH_BOOT_IMAGE
#include
! #define KERNEL_IMAGE_ADDRESS 0xffc00000
! #define KERNEL_IMG_SIZE_MAX 0x00400000
struct flash_dev_func* flash = NULL;
- #define FLAG_ADDR 0xfff70000
-
void dbg_mode(void);
#endif
--- 35,46 ----
#ifdef FLASH_BOOT_IMAGE
#include
+ #include
! #define KERNEL_IMAGE_ADDRESS 0xff000000
! #define KERNEL_IMG_SIZE_MAX 0x00f00000
struct flash_dev_func* flash = NULL;
void dbg_mode(void);
#endif
***************
*** 125,138 ****
timer++;
if(timer>next_timer) {
if(led_count>0) {
! if(led_count & 1)
HWCtl_Led_Down(LED_DIAG);
else
HWCtl_Led_Up(LED_DIAG);
led_count--;
! if(led_count == 0)
next_timer = 6000;
! else
next_timer = 1000;
}
if(led_count==0) led_count = warn_count*2;
--- 124,137 ----
timer++;
if(timer>next_timer) {
if(led_count>0) {
! if(led_count & 1)
HWCtl_Led_Down(LED_DIAG);
else
HWCtl_Led_Up(LED_DIAG);
led_count--;
! if(led_count == 0)
next_timer = 6000;
! else
next_timer = 1000;
}
if(led_count==0) led_count = warn_count*2;
***************
*** 170,176 ****
int i;
extern unsigned long start;
char *cp, ch;
- struct bi_record *rec, *birecs;
#ifdef FLASH_BOOT_IMAGE
struct firminfo* info;
--- 169,174 ----
***************
*** 181,201 ****
com_port = serial_init(1,CONSOLE_PORT);
#ifdef FLASH_BOOT_IMAGE
!
! if (check_pci_device(11, VID_REALTEK, DID_RTL8110S, 0) != 0)
! if (check_pci_device(11, VID_REALTEK, DID_RTL8110S_NULL, 0) != 0)
! if (check_pci_device(11, 0xEC10, 0x6981, 0) != 0) {
! puts("not found RTL8110S!\n");
! while(1) outb(0x80004500, 0x6F);
! }
!
! if (check_pci_device(12, VID_SiI, DID_SiI680, 0) != 0)
! while(1) outb(0x80004500, 0x6F);
!
! if ((check_pci_device(14, VID_NEC, DID_720101_U1, 0) != 0) ||
! (check_pci_device(14, VID_NEC, DID_720101_U2, 2) != 0))
! while(1) outb(0x80004500, 0x6F);
!
#endif
/* assume the chunk below 8M is free */
--- 179,187 ----
com_port = serial_init(1,CONSOLE_PORT);
#ifdef FLASH_BOOT_IMAGE
! if ((check_pci_device(11, VID_ADMTEK, DID_AN983B) != 0) ||
! (check_pci_device(12, VID_SiI, DID_SiI680) != 0))
! while(1) outb(0x80004500, 0x3A);
#endif
/* assume the chunk below 8M is free */
***************
*** 230,236 ****
_printk("Fail!:invalid Firmware size\n");
warn_count = 2;
timer_proc = warning_led;
! while(1) outb(0x80004500, 0x6B);
}
if (info->initrd_size < 1
--- 216,222 ----
_printk("Fail!:invalid Firmware size\n");
warn_count = 2;
timer_proc = warning_led;
! while(1) outb(0x80004500, 0x29);
}
if (info->initrd_size < 1
***************
*** 245,252 ****
_printk("Fail!:checksum error %08X\n",checksum_check((unsigned char*)info,info->size));
warn_count = 2;
timer_proc = warning_led;
! while(1) outb(0x80004500, 0x6B);
}
_printk("done.\n");
zimage_start = (char*)info + info->kernel_offset;
zimage_size = (int)info->kernel_size;
--- 231,239 ----
_printk("Fail!:checksum error %08X\n",checksum_check((unsigned char*)info,info->size));
warn_count = 2;
timer_proc = warning_led;
! while(1) outb(0x80004500, 0x2A);
}
+
_printk("done.\n");
zimage_start = (char*)info + info->kernel_offset;
zimage_size = (int)info->kernel_size;
***************
*** 254,260 ****
initrd_start = (unsigned long)((char*)info + info->initrd_offset);
initrd_end = initrd_start + info->initrd_size;
! if(initrd_start > 0xffc00000 && initrd_end<0xffefffff) {
avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
memcpy ((void *)avail_ram, (void *)initrd_start, info->initrd_size);
initrd_start = (unsigned long)avail_ram;
--- 241,247 ----
initrd_start = (unsigned long)((char*)info + info->initrd_offset);
initrd_end = initrd_start + info->initrd_size;
! if(initrd_start > 0xff000000 && initrd_end<0xffefffff) {
avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
memcpy ((void *)avail_ram, (void *)initrd_start, info->initrd_size);
initrd_start = (unsigned long)avail_ram;
***************
*** 310,316 ****
puts(" "); puthex(initrd_end); puts("\n");
}
} else if ( initrd_start ) {
! if ((unsigned long)zimage_start >= 0xffc00000) {
memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
zimage_start = (char *)avail_ram;
puts("relocated to: "); puthex((unsigned long)zimage_start);
--- 297,303 ----
puts(" "); puthex(initrd_end); puts("\n");
}
} else if ( initrd_start ) {
! if ((unsigned long)zimage_start >= 0xff000000) {
memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
zimage_start = (char *)avail_ram;
puts("relocated to: "); puthex((unsigned long)zimage_start);
***************
*** 382,405 ****
gunzip(0, 0x400000, zimage_start, &zimage_size);
puts("done.\n");
- outb(0x80004500, 0x49);
- outb(0x80004500, 0x49);
- outb(0x80004500, 0x49);
- outb(0x80004500, 0x49);
-
- udelay(10000);
- outb(0x80004500, 0x5D);
- outb(0x80004500, 0x5D);
- outb(0x80004500, 0x5D);
- outb(0x80004500, 0x5D);
-
puts("Now Booting\n");
}
#ifdef FLASH_BOOT_IMAGE
#define b2llong(a) \
((a & 0xff000000)>>24) + ((a & 0x00ff0000)>>8) + \
! ((a & 0x0000ff00)<<8 ) + ((a & 0x000000ff)<<24)
#define bit(a) 1<>24) + ((a & 0x00ff0000)>>8) + \
! ((a & 0x0000ff00)<<8 ) + ((a & 0x000000ff)<<24)
#define bit(a) 1<
struct flash_dev_func* flash_list[] = {
&flash_toshiba,
--- 445,451 ----
#define printk _printk
! #include
struct flash_dev_func* flash_list[] = {
&flash_toshiba,
***************
*** 517,527 ****
unsigned long *datap,data;
int i;
static int tgl = 0;
!
str_trim(¶m);
arg1 = str_trim(¶m);
arg2 = str_trim(¶m);
!
if(*arg1 != '\0' && arg2 != '\0') {
adr = hextolong(arg1);
if(adr >= 0x10000 || adr & 0x0f) return DBG_NG_OUT_OF_AREA;
--- 493,503 ----
unsigned long *datap,data;
int i;
static int tgl = 0;
!
str_trim(¶m);
arg1 = str_trim(¶m);
arg2 = str_trim(¶m);
!
if(*arg1 != '\0' && arg2 != '\0') {
adr = hextolong(arg1);
if(adr >= 0x10000 || adr & 0x0f) return DBG_NG_OUT_OF_AREA;
***************
*** 542,548 ****
}
}
else return DBG_NG_FEW_PARAM;
!
if(tgl) {HWCtl_Led_Down(LED_BLINK1);HWCtl_Led_Up(LED_BLINK2);}
else {HWCtl_Led_Down(LED_BLINK2);HWCtl_Led_Up(LED_BLINK1);}
tgl = (tgl==0);
--- 518,524 ----
}
}
else return DBG_NG_FEW_PARAM;
!
if(tgl) {HWCtl_Led_Down(LED_BLINK1);HWCtl_Led_Up(LED_BLINK2);}
else {HWCtl_Led_Down(LED_BLINK2);HWCtl_Led_Up(LED_BLINK1);}
tgl = (tgl==0);
***************
*** 569,581 ****
_printk("checksum fail:%08X %08X\n",sum,checksum_check(buff,0x10000));
return DBG_NG_SUM_ERROR;
}
! if(adrKERNEL_IMAGE_ADDRESS+KERNEL_IMG_SIZE_MAX
|| adr+0x10000>KERNEL_IMAGE_ADDRESS+KERNEL_IMG_SIZE_MAX
|| (adr & 0x0000ffff) > 0) {
return DBG_NG_OUT_OF_AREA;
}
!
{HWCtl_Led_Down(LED_BLINK1);HWCtl_Led_Up(LED_BLINK2);}
if(flash->blk_erase(adr,1)) {
return DBG_NG_FAIL_ERASE;
--- 545,557 ----
_printk("checksum fail:%08X %08X\n",sum,checksum_check(buff,0x10000));
return DBG_NG_SUM_ERROR;
}
! if(adrKERNEL_IMAGE_ADDRESS+KERNEL_IMG_SIZE_MAX
|| adr+0x10000>KERNEL_IMAGE_ADDRESS+KERNEL_IMG_SIZE_MAX
|| (adr & 0x0000ffff) > 0) {
return DBG_NG_OUT_OF_AREA;
}
!
{HWCtl_Led_Down(LED_BLINK1);HWCtl_Led_Up(LED_BLINK2);}
if(flash->blk_erase(adr,1)) {
return DBG_NG_FAIL_ERASE;
***************
*** 637,643 ****
return DBG_OK;
}
! int dbg_ledstop(char* p)
{
timer_proc = NULL;
return 0;
--- 613,619 ----
return DBG_OK;
}
! int dbg_ledstop(char* p)
{
timer_proc = NULL;
return 0;
***************
*** 662,668 ****
{NULL, NULL}
};
! int dbg_help(char* p)
{
struct dbg_cmdlist* list = dbg_commands;
int j,i;
--- 638,644 ----
{NULL, NULL}
};
! int dbg_help(char* p)
{
struct dbg_cmdlist* list = dbg_commands;
int j,i;
***************
*** 710,721 ****
}
}
! void print_pci_config_reg(unsigned long idsel, unsigned long fn) {
unsigned int offset;
unsigned long reg, in_reg;
! reg = (0x80 << 24) + (idsel << 11) + (fn << 8);
_printk("PCI IDSEL%d device configuration registers\n", idsel);
for (offset = 0x00; offset < 0x40; offset += 4) {
--- 686,710 ----
}
}
! void print_pci_config_reg(int idsel) {
unsigned int offset;
unsigned long reg, in_reg;
! switch (idsel) {
! case 11:
! reg = 0x80005800UL;
! break;
! case 12:
! reg = 0x80006000UL;
! break;
! case 13:
! reg = 0x80006800UL;
! break;
! default:
! reg = 0x80006000UL;
! break;
! }
_printk("PCI IDSEL%d device configuration registers\n", idsel);
for (offset = 0x00; offset < 0x40; offset += 4) {
***************
*** 724,729 ****
}
}
! #endif // #ifdef FLASH_BOOT_IMAGE
--- 713,718 ----
}
}
! #endif
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/boot/sandpoint/head.S LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/boot/sandpoint/head.S
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/boot/sandpoint/head.S 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/boot/sandpoint/head.S 2004-05-24 17:35:29.000000000 +0900
***************
*** 20,26 ****
#include
#include
! #define RAM_SIZE 0x08000000
#define DEC_COUNT 0x00002000
#define WM32(address,data) \
--- 20,26 ----
#include
#include
! #define RAM_SIZE 0x04000000
#define DEC_COUNT 0x00002000
#define WM32(address,data) \
***************
*** 70,77 ****
#endif
start:
! bl start_
!
#ifdef FLASH_BOOT_IMAGE
.space (0x100-4)
rfi
--- 70,77 ----
#endif
start:
! bl start_
!
#ifdef FLASH_BOOT_IMAGE
.space (0x100-4)
rfi
***************
*** 156,176 ****
mtspr HID0,r4
sync
isync
!
ori r4,r4,0x8000
ori r8,r4,0x0800
isync
mtspr HID0,r8
sync
isync
!
mtspr HID0,r4
sync
isync
#ifdef FLASH_BOOT_IMAGE
! melco_config_start:
WM32(0xFEC00000,0x0d000080)
WM8(0xFEE00001,0x20)
WM32(0xFEC00000,0x0c000080)
--- 156,176 ----
mtspr HID0,r4
sync
isync
!
ori r4,r4,0x8000
ori r8,r4,0x0800
isync
mtspr HID0,r8
sync
isync
!
mtspr HID0,r4
sync
isync
#ifdef FLASH_BOOT_IMAGE
! melco_config_start:
WM32(0xFEC00000,0x0d000080)
WM8(0xFEE00001,0x20)
WM32(0xFEC00000,0x0c000080)
***************
*** 178,199 ****
WM32(0xFEC00000,0x04000080)
WM16(0xFEE00000,0x0600)
WM32(0xFEC00000,0xa8000080)
! lis r3, 0xFEE00000@h
ori r3, r3, 0xFEE00000@l
!
lwz r5, 0(r3)
lis r4, 0x0
ori r4, r4, 0x1000
and r5, r4, r5
!
lis r4, 0xd8130400@h
ori r4, r4, 0xd8130400@l
or r4, r4, r5
!
stw r4, 0x0000(r3)
sync
isync
!
WM32(0xFEC00000,0xac000080)
WM32(0xFEE00000,0x00000004)
WM32(0xFEC00000,0x78000080)
--- 178,199 ----
WM32(0xFEC00000,0x04000080)
WM16(0xFEE00000,0x0600)
WM32(0xFEC00000,0xa8000080)
! lis r3, 0xFEE00000@h
ori r3, r3, 0xFEE00000@l
!
lwz r5, 0(r3)
lis r4, 0x0
ori r4, r4, 0x1000
and r5, r4, r5
!
lis r4, 0xd8130400@h
ori r4, r4, 0xd8130400@l
or r4, r4, r5
!
stw r4, 0x0000(r3)
sync
isync
!
WM32(0xFEC00000,0xac000080)
WM32(0xFEE00000,0x00000004)
WM32(0xFEC00000,0x78000080)
***************
*** 215,221 ****
WM32(0xFEC00000,0x84000080)
WM32(0xFEE00000,0xFFFFFFFF)
WM32(0xFEC00000,0x90000080)
! WM32(0xFEE00000,0x7FFFFFFF)
WM32(0xFEC00000,0x94000080)
WM32(0xFEE00000,0xFFFFFFFF)
WM32(0xFEC00000,0x88000080)
--- 215,221 ----
WM32(0xFEC00000,0x84000080)
WM32(0xFEE00000,0xFFFFFFFF)
WM32(0xFEC00000,0x90000080)
! WM32(0xFEE00000,0x3FFFFFFF)
WM32(0xFEC00000,0x94000080)
WM32(0xFEE00000,0xFFFFFFFF)
WM32(0xFEC00000,0x88000080)
***************
*** 227,247 ****
WM32(0xFEC00000,0x9C000080)
WM32(0xFEE00000,0x03030303)
WM32(0xFEC00000,0xf0000080)
! WM32(0xFEE00000,0x0200E005)
WM32(0xFEC00000,0xf4000080)
! WM32(0xFEE00000,0x8015000e)
! WM32(0xFEC00000,0xf8000080)
WM32(0xFEE00000,0x00000077)
WM32(0xFEC00000,0xfc000080)
! WM32(0xFEE00000,0x29323222)
WM32(0xFEC00000,0x73000080)
! WM8(0xFEE00003,0x15)
WM32(0xFEC00000,0x74000080)
WM16(0xFEE00000,0x7078)
WM32(0xFEC00000,0xa0000080)
WM8(0xFEE00000, 0x01)
WM32(0xFEC00000,0xa3000080)
! WM8(0xFEE00003,0xC9)
WM32(0xFEC00000,0xd0000080)
WM32(0xFEE00000,0xffffff85)
WM32(0xFEC00000,0xd4000080)
--- 227,247 ----
WM32(0xFEC00000,0x9C000080)
WM32(0xFEE00000,0x03030303)
WM32(0xFEC00000,0xf0000080)
! WM32(0xFEE00000,0x0000E005)
WM32(0xFEC00000,0xf4000080)
! WM32(0xFEE00000,0xe015000e)
! WM32(0xFEC00000,0xf8000080)
WM32(0xFEE00000,0x00000077)
WM32(0xFEC00000,0xfc000080)
! WM32(0xFEE00000,0x29223222)
WM32(0xFEC00000,0x73000080)
! WM8(0xFEE00003,0x95)
WM32(0xFEC00000,0x74000080)
WM16(0xFEE00000,0x7078)
WM32(0xFEC00000,0xa0000080)
WM8(0xFEE00000, 0x01)
WM32(0xFEC00000,0xa3000080)
! WM8(0xFEE00003,0x92)
WM32(0xFEC00000,0xd0000080)
WM32(0xFEE00000,0xffffff85)
WM32(0xFEC00000,0xd4000080)
***************
*** 251,270 ****
WM32(0xFEC00000,0xdc000080)
WM32(0xFEE00000,0x0e000000)
WM32(0xFEC00000,0xf0000080)
! WM32(0xFEE00000,0x0200E805)
WM8(0x80004503,0x00)
WM8(0x80004501,0x00)
WM8(0x80004503,0x80)
WM8(0x80004511,0x01)
! WM8(0x80004500,0x61)
! WM8(0x80004501,0x03)
WM8(0x80004503,0x1b)
WM8(0x80004500,0x00)
WM8(0x80004502,0x07)
! melco_config_end:
#endif
!
lis r3, 0x8000
ori r3, r3, 0x0004
lis r4, 0xFEC0
--- 251,270 ----
WM32(0xFEC00000,0xdc000080)
WM32(0xFEE00000,0x0e000000)
WM32(0xFEC00000,0xf0000080)
! WM32(0xFEE00000,0x0000E805)
WM8(0x80004503,0x00)
WM8(0x80004501,0x00)
WM8(0x80004503,0x80)
WM8(0x80004511,0x01)
! WM8(0x80004500,0x8B)
! WM8(0x80004501,0x02)
WM8(0x80004503,0x1b)
WM8(0x80004500,0x00)
WM8(0x80004502,0x07)
! melco_config_end:
#endif
!
lis r3, 0x8000
ori r3, r3, 0x0004
lis r4, 0xFEC0
***************
*** 282,306 ****
#ifdef FLASH_BOOT_IMAGE
check_ram:
- lis r3, 1000
- mulli r4,r3,1000
- addi r4,r4,59
- li r5,60
- divw r4,r4,r5
- 1: mftbu r5
- mftb r6
- mftbu r7
- cmp 0,r5,r7
- bne 1b
- addc r9,r6,r4
- addze r8,r5
- 2: mftbu r5
- cmp 0,r5,r8
- blt 2b
- bgt 3f
- mftb r6
- cmp 0,r6,r9
- blt 2b
xor r4,r4,r4
lis r5, RAM_SIZE@h
ori r5, r5, RAM_SIZE@l
--- 282,287 ----
***************
*** 310,316 ****
ori r7, r7, 0x5555
lis r8, 0x0000
ori r8, r8, 0x0100
! check_ram_loop:
cmp 0,r4,r5
beq check_ram_end
stw r6,0(r4)
--- 291,297 ----
ori r7, r7, 0x5555
lis r8, 0x0000
ori r8, r8, 0x0100
! check_ram_loop:
cmp 0,r4,r5
beq check_ram_end
stw r6,0(r4)
***************
*** 328,334 ****
add r4,r4,r8
b check_ram_loop
ram_error:
! WM8(0x80004500,0x6F)
b ram_error
check_ram_end:
#endif
--- 309,315 ----
add r4,r4,r8
b check_ram_loop
ram_error:
! WM8(0x80004500,0x39)
b ram_error
check_ram_end:
#endif
***************
*** 433,441 ****
stwu r1,-16(r1)
stw r3,8(r1)
stw r4,12(r1)
!
WM32(timer_proc,0x00000000)
!
lis r4 , 0x0
ori r4,r4,0x400 /* 1000 clock */
sync
--- 414,422 ----
stwu r1,-16(r1)
stw r3,8(r1)
stw r4,12(r1)
!
WM32(timer_proc,0x00000000)
!
lis r4 , 0x0
ori r4,r4,0x400 /* 1000 clock */
sync
***************
*** 452,458 ****
mtmsr r3
sync
isync
!
lwz r3,8(r1)
lwz r4,12(r1)
la r1,16(r1)
--- 433,439 ----
mtmsr r3
sync
isync
!
lwz r3,8(r1)
lwz r4,12(r1)
la r1,16(r1)
***************
*** 462,468 ****
stwu r1,-16(r1)
stw r3,8(r1)
stw r4,12(r1)
!
mfmsr r3
li r4,0
ori r4,r4,MSR_EE
--- 443,449 ----
stwu r1,-16(r1)
stw r3,8(r1)
stw r4,12(r1)
!
mfmsr r3
li r4,0
ori r4,r4,MSR_EE
***************
*** 472,478 ****
mtmsr r3
sync
isync
!
lwz r3,8(r1)
lwz r4,12(r1)
la r1,16(r1)
--- 453,459 ----
mtmsr r3
sync
isync
!
lwz r3,8(r1)
lwz r4,12(r1)
la r1,16(r1)
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/melco_hwctl.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/melco_hwctl.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/melco_hwctl.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/melco_hwctl.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 241,252 ****
return ret;
}
! int check_pci_device(int idsel, unsigned short vid, unsigned short did, int fn)
{
unsigned int offset;
unsigned long base, in_reg;
! base = (0x80 << 24) + (idsel << 11) + (fn << 8);
out_ledw((unsigned long *)PCI_CONFIG_ADDR, base);
in_reg = in_ledw((unsigned long *)PCI_CONFIG_DATA);
--- 241,266 ----
return ret;
}
! int check_pci_device(int idsel, unsigned short vid, unsigned short did)
{
+
unsigned int offset;
unsigned long base, in_reg;
! switch (idsel) {
! case 11:
! base = 0x80005800UL;
! break;
! case 12:
! base = 0x80006000UL;
! break;
! case 13:
! base = 0x80006800UL;
! break;
! default:
! base = 0x80006000UL;
! break;
! }
out_ledw((unsigned long *)PCI_CONFIG_ADDR, base);
in_reg = in_ledw((unsigned long *)PCI_CONFIG_DATA);
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/melco_rtc.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/melco_rtc.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/melco_rtc.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/melco_rtc.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 227,232 ****
--- 227,233 ----
int hid0;
melco_rtc_init();
+ #if 0
loop_count = 0;
sec = melco_get_sec();
***************
*** 254,263 ****
freq -= tbl;
} while ((get_tbu() != tbu) && (++loop_count < 2));
! if (freq > 32700000)
! freq = 32768000;
! tb_ticks_per_jiffy = freq / HZ;
! tb_to_us = mulhwu_scale_factor(freq, 1000000);
printk("decrementer frequency = %ld.%6ld MHz \n", freq / 1000000, freq % 1000000);
return;
--- 255,264 ----
freq -= tbl;
} while ((get_tbu() != tbu) && (++loop_count < 2));
! #endif
! freq = 32768000*3;
! tb_ticks_per_jiffy = freq / HZ / 4;
! tb_to_us = mulhwu_scale_factor(freq / 4, 1000000);
printk("decrementer frequency = %ld.%6ld MHz \n", freq / 1000000, freq % 1000000);
return;
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/open_pic.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/open_pic.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/open_pic.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/open_pic.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 373,378 ****
--- 373,379 ----
if (sense)
irq_desc[i+offset].status = IRQ_LEVEL;
+ /* Enabled, Priority 8 or 9 */
openpic_initirq(i, pri, i+offset, !sense, sense);
/* Processor 0 */
openpic_mapirq(i, 1<<0);
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/time.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/time.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/kernel/time.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/kernel/time.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 325,333 ****
melco_check_callender();
} else {
ulong freq;
! freq = 32768000;
! tb_ticks_per_jiffy = freq / HZ;
! tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
}
--- 325,333 ----
melco_check_callender();
} else {
ulong freq;
! freq = 32768000*3;
! tb_ticks_per_jiffy = freq / HZ / 4;
! tb_to_us = mulhwu_scale_factor(freq / 4, 1000000);
}
}
***************
*** 351,356 ****
--- 351,358 ----
if (sec==old_sec) {
printk("Warning: real time clock seems stuck!\n");
}
+ printk("rtc sec count %ld\n", sec);
+
write_lock_irqsave(&xtime_lock, flags);
xtime.tv_sec = sec;
last_jiffy_stamp(0) = tb_last_stamp = stamp;
***************
*** 456,462 ****
int day_max = 28;
int cal_error = 0;
tm = melco_get_rtc2();
! if (tm.tm_year < 2003 || tm.tm_year > 2038) {
cal_error = 1;
}
--- 458,464 ----
int day_max = 28;
int cal_error = 0;
tm = melco_get_rtc2();
! if (tm.tm_year < 2002 || tm.tm_year > 2038) {
cal_error = 1;
}
***************
*** 492,499 ****
}
if (cal_error) {
! tm.tm_year = 2003;
! tm.tm_mon = 11;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
--- 494,501 ----
}
if (cal_error) {
! tm.tm_year = 2002;
! tm.tm_mon = 1;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/mm/ppc_mmu.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/mm/ppc_mmu.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/mm/ppc_mmu.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/mm/ppc_mmu.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 92,97 ****
--- 92,100 ----
unsigned long tot, done;
+ setbat(2, 0x80000000, 0x80000000, 0x01000000, _PAGE_IO);
+ setbat(3, 0xf8000000, 0xf8000000, 0x08000000, _PAGE_IO);
+
tot = total_lowmem;
setbat(2, KERNELBASE, PPC_MEMSTART, bat2, _PAGE_KERNEL);
done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/platforms/sandpoint_pci.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/platforms/sandpoint_pci.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/platforms/sandpoint_pci.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/platforms/sandpoint_pci.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 38,45 ****
{
{ 16, 19, 18, 17 },
{ 17, 16, 19, 18 },
! { 19, 19, 19, 16 },
! { 19, 19, 19, 16 },
};
const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
--- 38,45 ----
{
{ 16, 19, 18, 17 },
{ 17, 16, 19, 18 },
! { 18, 17, 16, 19 },
! { 19, 18, 17, 16 },
};
const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/platforms/sandpoint_setup.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/platforms/sandpoint_setup.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/arch/ppc/platforms/sandpoint_setup.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/arch/ppc/platforms/sandpoint_setup.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 110,115 ****
--- 110,116 ----
static void sandpoint_halt(void);
+
/*
* *** IMPORTANT ***
*
***************
*** 141,147 ****
1,
1,
1,
! 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
--- 142,148 ----
1,
1,
1,
! 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
***************
*** 163,169 ****
1,
1,
1
! #endif
};
static void __init
--- 164,170 ----
1,
1,
1
! #endif // #ifdef CONFIG_SANDPOINT_X3
};
static void __init
***************
*** 182,187 ****
--- 183,190 ----
ROOT_DEV = to_kdev_t(0x0301); /* /dev/hda1 IDE disk */
#endif
+ HWCtl_Init();
+
/* Lookup PCI host bridges */
sandpoint_find_bridges();
***************
*** 190,197 ****
conswitchp = &dummy_con;
#endif
! printk("BUFFALO Network Attached Storage Series\n");
! printk("(C) 2002,3 BUFFALO INC.\n");
/* The Sandpoint rom doesn't enable any caches. Do that now.
* The 7450 portion will also set up the L3s once I get enough
--- 193,200 ----
conswitchp = &dummy_con;
#endif
! printk("MELCO Network Attached Storage Series\n");
! printk("2002 MELCO INC.\n");
/* The Sandpoint rom doesn't enable any caches. Do that now.
* The 7450 portion will also set up the L3s once I get enough
***************
*** 393,399 ****
{
ulong size = 0;
! size = 128*1024*1024;
return size;
}
--- 396,402 ----
{
ulong size = 0;
! size = 64*1024*1024;
return size;
}
***************
*** 401,407 ****
static void __init
sandpoint_map_io(void)
{
- io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
io_block_mapping(MPC10X_MAPB_EUMB_BASE, MPC10X_MAPB_EUMB_BASE,
MPC10X_EUMB_SIZE, _PAGE_IO);
--- 404,409 ----
***************
*** 414,419 ****
--- 416,431 ----
sandpoint_restart(char *cmd)
{
__cli();
+
+ out_8(0x80004503, 0x80);
+ out_8(0x80004511, 0x01);
+
+ out_8(0x80004500, ((100000000 / 16) / 9600));
+ out_8(0x80004501, ((100000000 / 16) / 9600) >> 8);
+
+ out_8(0x80004503, 0x1b);
+ out_8(0x80004502, 0x07);
+
#if 0
/* Set exception prefix high - to the firmware */
_nmask_and_or_msr(0, MSR_IP);
***************
*** 431,436 ****
--- 443,458 ----
{
__cli();
+ out_8(0x80004503, 0x80);
+ out_8(0x80004511, 0x01);
+
+ out_8(0x80004500, ((100000000 / 16) / 9600));
+ out_8(0x80004501, ((100000000 / 16) / 9600) >> 8);
+
+ out_8(0x80004502, 0x00);
+
+ out_8(0x80004503, 0x1b);
+ out_8(0x80004502, 0x07);
for(;;) /* No way to shut power off with software */
out_8(0x80004500, 0x47);
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/block/acsi.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/block/acsi.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/block/acsi.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/block/acsi.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1403,1410 ****
"WORM ",
"CD-ROM ",
"Scanner ",
! "Optical-Device ",
! "Medium-Changer ",
"Communications "
};
--- 1403,1410 ----
"WORM ",
"CD-ROM ",
"Scanner ",
! "Optical Device ",
! "Medium Changer ",
"Communications "
};
***************
*** 1446,1456 ****
printk(KERN_INFO " Type: %s ", (i < MAX_SCSI_DEVICE_CODE
? scsi_device_types[i]
: "Unknown "));
! printk(" RMB: %s", (data[0] & 0x80) ?
! "Removable" : "HardDisk");
! printk("\n");
! printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
!
if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
printk(" CCS\n");
else
--- 1446,1452 ----
printk(KERN_INFO " Type: %s ", (i < MAX_SCSI_DEVICE_CODE
? scsi_device_types[i]
: "Unknown "));
! printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
printk(" CCS\n");
else
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/block/flashdisk/flashdisk.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/block/flashdisk/flashdisk.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/block/flashdisk/flashdisk.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/block/flashdisk/flashdisk.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 45,50 ****
--- 45,51 ----
#include
#include
+ #include
#define dbg_printk(args...)
***************
*** 53,70 ****
static devfs_handle_t devfs_handle;
struct flash_dev_func* flash_dev_list[] = {
! &flash_st,
&flash_fujitsu,
- &flash_mx,
NULL
};
struct flashd_list area_list[] = {
{ 0xFFF80000, 0x80000 , ROM_ON_BORD },
! { 0xFFC00000, 0x300000 , ROM_ON_BORD },
! { 0xFFF00000, 0x70000 , ROM_ON_BORD },
! { 0xFFF70000, 0x10000 , ROM_ON_BORD },
! { 0xFFC00000, 0x400000 , ROM_ON_BORD },
{ 0xFFF80000, 0x80000 , ROM_MINIPCI },
{ 0xFF800000, 0x600000 , ROM_MINIPCI },
{ 0xFFF00000, 0x80000 , ROM_MINIPCI },
--- 54,68 ----
static devfs_handle_t devfs_handle;
struct flash_dev_func* flash_dev_list[] = {
! &flash_toshiba,
&flash_fujitsu,
NULL
};
struct flashd_list area_list[] = {
{ 0xFFF80000, 0x80000 , ROM_ON_BORD },
! { 0xFF000000, 0xF00000 , ROM_ON_BORD },
! { 0xFFF00000, 0x80000 , ROM_ON_BORD },
{ 0xFFF80000, 0x80000 , ROM_MINIPCI },
{ 0xFF800000, 0x600000 , ROM_MINIPCI },
{ 0xFFF00000, 0x80000 , ROM_MINIPCI },
***************
*** 81,87 ****
int isopened;
int boot_from_mini_pci=0;
- int modifying_cash;
#define FLASHD_BLOCK_SIZE 1*1024
--- 79,84 ----
***************
*** 188,200 ****
if(cacheinfo.dev->rom_type == ROM_MINIPCI) write_enable_winbond(dev_winbond);
! if(dev->blk_erase((unsigned long)cacheinfo.addr,1) != 0) {
! printk("FLASHDISK:Fatal! Can't Erase Flash!\n");
if(is_blink == 1) blink_led(FLASH_UPDATE_END);
return -1;
}
! if(dev->blk_write((unsigned long)cacheinfo.addr,flash_cache,cacheinfo.size) != 0) {
printk("FLASHDISK:Fatal! Can't Write Flash!\n");
if(is_blink == 1) blink_led(FLASH_UPDATE_END);
return -1;
--- 185,197 ----
if(cacheinfo.dev->rom_type == ROM_MINIPCI) write_enable_winbond(dev_winbond);
! if(dev->blk_erase((unsigned long)cacheinfo.addr,1)) {
! printk("FLASHDISK:Fatal! Can't Erase Flash!");
if(is_blink == 1) blink_led(FLASH_UPDATE_END);
return -1;
}
! if(dev->blk_write((unsigned long)cacheinfo.addr,flash_cache,cacheinfo.size)) {
printk("FLASHDISK:Fatal! Can't Write Flash!\n");
if(is_blink == 1) blink_led(FLASH_UPDATE_END);
return -1;
***************
*** 401,414 ****
int len = 0;
char* buf = page;
struct firminfo* info;
- unsigned long *boot_flag;
if (boot_from_mini_pci)
info = (struct firminfo*)0xFF800000;
else
! info = (struct firminfo*)0xFFC00000;
! boot_flag = (unsigned long *)0xFFF70000;
len += sprintf(buf+len,"PRODUCTNAME=");
i=0;
while(ifirmname[i] != 0) {
--- 398,410 ----
int len = 0;
char* buf = page;
struct firminfo* info;
if (boot_from_mini_pci)
info = (struct firminfo*)0xFF800000;
else
! info = (struct firminfo*)0xFF000000;
+
len += sprintf(buf+len,"PRODUCTNAME=");
i=0;
while(ifirmname[i] != 0) {
***************
*** 427,438 ****
len += sprintf(buf+len,"BUILDDATE=%d/%d/%d %d:%d:%d\n", info->year+1900,info->mon,info->day,
info->hour,info->min,info->sec);
if(boot_from_mini_pci) len += sprintf(buf+len,"MINI_PCI_BOOT\n");
- if(*boot_flag == 0x4e474e47)
- len += sprintf(buf+len,"BOOTFLAG=NG\n");
- else if(*boot_flag == 0x4f4b4f4b)
- len += sprintf(buf+len,"BOOTFLAG=OK\n");
- else
- len += sprintf(buf+len,"BOOTFLAG=OTHER\n");
if (len <= off+count) *eof = 1;
*start = page + off;
--- 423,428 ----
***************
*** 451,457 ****
int __init flashd_init (void)
{
int i;
! struct flash_dev_func* flash[1];
unsigned char dev = 0;
unsigned long total_size = 0;
--- 441,447 ----
int __init flashd_init (void)
{
int i;
! struct flash_dev_func* flash[2];
unsigned char dev = 0;
unsigned long total_size = 0;
***************
*** 562,568 ****
blk_size[MAJOR_NR] = flashd_kbsize;
isopened = 0;
!
create_proc_read_entry("asconf_info", 0, NULL, flashd_read_proc, NULL);
printk("Initialized ");
--- 552,558 ----
blk_size[MAJOR_NR] = flashd_kbsize;
isopened = 0;
!
create_proc_read_entry("asconf_info", 0, NULL, flashd_read_proc, NULL);
printk("Initialized ");
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/char/mel_rtc.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/char/mel_rtc.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/char/mel_rtc.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/char/mel_rtc.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 84,109 ****
return len;
}
- static int mel_rtc_read_proc2(char *page, char **start, off_t off,
- int count, int *eof, void *data)
- {
- char *p = page;
- int len;
- unsigned long time_sec;
-
- __cli();
- time_sec = melco_get_rtc();
- p += sprintf(p, "%ld\n", time_sec);
- __sti();
- len = (int) (p - page);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
- return len;
- }
-
static int mel_rtc_open(struct inode *inode, struct file *file)
{
--- 84,89 ----
***************
*** 144,149 ****
--- 124,130 ----
};
+ /*-------------------*/
static int ap_read_procmem(char *page, char **start, off_t off,int count, int *eof, void *data){
#define LIMIT (PAGE_SIZE-80)
***************
*** 159,165 ****
return len;
}
-
static const char banner[] __initdata = KERN_INFO "MELCO INC. RTC driver ver 1.00\n";
#define PROC_APINFO "as_info"
--- 140,145 ----
***************
*** 173,179 ****
return ret;
create_proc_read_entry ("driver/rtc", 0, 0, mel_rtc_read_proc, NULL);
- create_proc_read_entry ("driver/rtc2", 0, 0, mel_rtc_read_proc2, NULL);
create_proc_read_entry (PROC_APINFO, 0, 0, &ap_read_procmem, NULL);
printk(banner);
--- 153,158 ----
***************
*** 184,190 ****
static void __exit mel_rtc_exit(void)
{
remove_proc_entry("driver/rtc", NULL);
- remove_proc_entry("driver/rtc2", NULL);
remove_proc_entry(PROC_APINFO,NULL);
misc_deregister(&mel_rtc_miscdev);
}
--- 163,168 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/char/rtc.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/char/rtc.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/char/rtc.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/char/rtc.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 327,333 ****
* tm_min, and tm_sec values are filled in.
*/
- memset(&wtime, 0, sizeof(struct rtc_time)); // BUFFALO add
get_rtc_alm_time(&wtime);
break;
}
--- 327,332 ----
***************
*** 375,381 ****
}
case RTC_RD_TIME: /* Read the time/date from RTC */
{
- memset(&wtime, 0, sizeof(struct rtc_time)); // BUFFALO add
get_rtc_time(&wtime);
break;
}
--- 374,379 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net/Config.in LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/net/Config.in
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net/Config.in 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/net/Config.in 2004-05-24 17:35:29.000000000 +0900
***************
*** 281,290 ****
dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI
- dep_tristate 'Realtek R8110S/R8169S support' CONFIG_R8169 $CONFIG_PCI
- if [ "$CONFIG_R8169" = "y" ]; then
- bool ' Support RTL8169 Jumbo Frame' RTL8169_JUMBO_FRAME_SUPPORT
- fi
endmenu
--- 281,286 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net/Makefile LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/net/Makefile
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net/Makefile 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/net/Makefile 2004-05-24 17:35:29.000000000 +0900
***************
*** 41,47 ****
subdir-$(CONFIG_SK98LIN) += sk98lin
subdir-$(CONFIG_SKFP) += skfp
-
#
# link order important here
#
--- 41,46 ----
***************
*** 81,87 ****
obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_FEALNX) += fealnx.o
obj-$(CONFIG_TC35815) += tc35815.o
- obj-$(CONFIG_R8169) += r8169.o
ifeq ($(CONFIG_SK98LIN),y)
obj-y += sk98lin/sk98lin.o
--- 80,85 ----
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net$B$@$1$KH/8+(B: r8169.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net$B$@$1$KH/8+(B: r8169_ioctl.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net$B$@$1$KH/8+(B: r8169_ioctl.h
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net/tulip/tulip_core.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/net/tulip/tulip_core.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/net/tulip/tulip_core.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/net/tulip/tulip_core.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1096,1102 ****
}
data = (short*)mreq->u.mac.mac;
for (i = 4; i < 7; i++, data++) {
! rval = tulip_write_eeprom(ioaddr, i, ee_addr_size, le16_to_cpu(*data));
if (rval==0) {
printk("count %d Write EEPROM Error\n", i);
break;
--- 1096,1102 ----
}
data = (short*)mreq->u.mac.mac;
for (i = 4; i < 7; i++, data++) {
! rval = tulip_write_eeprom(ioaddr, i, 6, le16_to_cpu(*data));
if (rval==0) {
printk("count %d Write EEPROM Error\n", i);
break;
***************
*** 1209,1215 ****
}
}
spin_lock_irqsave(&tp->lock, flags);
! rval = tulip_write_eeprom(ioaddr, i, ee_addr_size, le16_to_cpu(data));
spin_unlock_irqrestore(&tp->lock, flags);
if (rval==0) {
printk("count %d Write EEPROM Error\n", i);
--- 1209,1215 ----
}
}
spin_lock_irqsave(&tp->lock, flags);
! rval = tulip_write_eeprom(ioaddr, i, 6, le16_to_cpu(data));
spin_unlock_irqrestore(&tp->lock, flags);
if (rval==0) {
printk("count %d Write EEPROM Error\n", i);
***************
*** 1223,1229 ****
eew[i] = (u16)tulip_read_eeprom(ioaddr, i, ee_addr_size);
sum += eew[i];
}
! tulip_write_eeprom(ioaddr, 0x3f, ee_addr_size, -sum);
spin_unlock_irqrestore(&tp->lock, flags);
}
--- 1223,1229 ----
eew[i] = (u16)tulip_read_eeprom(ioaddr, i, ee_addr_size);
sum += eew[i];
}
! tulip_write_eeprom(ioaddr, 0x3f, 6, -sum);
spin_unlock_irqrestore(&tp->lock, flags);
}
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/scsi/scsi.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/scsi/scsi.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/scsi/scsi.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/scsi/scsi.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 135,142 ****
"WORM ",
"CD-ROM ",
"Scanner ",
! "Optical-Device ",
! "Medium-Changer ",
"Communications ",
"Unknown ",
"Unknown ",
--- 135,142 ----
"WORM ",
"CD-ROM ",
"Scanner ",
! "Optical Device ",
! "Medium Changer ",
"Communications ",
"Unknown ",
"Unknown ",
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/scsi/scsi_proc.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/scsi/scsi_proc.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/scsi/scsi_proc.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/scsi/scsi_proc.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 288,302 ****
y += sprintf(buffer + len + y, "\n");
y += sprintf(buffer + len + y, " Type: %s ",
! scd->type < MAX_SCSI_DEVICE_CODE ?
! scsi_device_types[(int) scd->type] : "Unknown ");
! y += sprintf(buffer + len + y, " RMB: %s ",
! scd->removable ? "Removable" : "HardDisk");
!
! y += sprintf(buffer + len + y, "\n");
! y += sprintf(buffer + len + y, " ANSI"
! " SCSI revision: %02x", (scd->scsi_level - 1) ? scd->scsi_level - 1 : 1);
!
if (scd->scsi_level == 2)
y += sprintf(buffer + len + y, " CCS\n");
else
--- 288,297 ----
y += sprintf(buffer + len + y, "\n");
y += sprintf(buffer + len + y, " Type: %s ",
! scd->type < MAX_SCSI_DEVICE_CODE ?
! scsi_device_types[(int) scd->type] : "Unknown ");
! y += sprintf(buffer + len + y, " ANSI"
! " SCSI revision: %02x", (scd->scsi_level - 1) ? scd->scsi_level - 1 : 1);
if (scd->scsi_level == 2)
y += sprintf(buffer + len + y, " CCS\n");
else
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/CDCEther.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/CDCEther.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/CDCEther.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/CDCEther.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,4 ****
! // Portions of this file taken from
// Petko Manolov - Petkan (petkan@dce.bg)
// from his driver pegasus.c
--- 1,4 ----
! // Portions of this file taken from
// Petko Manolov - Petkan (petkan@dce.bg)
// from his driver pegasus.c
***************
*** 25,51 ****
#include
#include
#include
- #include
- #include
- #include
-
- #define DEBUG
#include
!
#include "CDCEther.h"
! #define SHORT_DRIVER_DESC "CDC Ethernet Class"
! #define DRIVER_VERSION "0.98.6"
! static const char *version = __FILE__ ": " DRIVER_VERSION " 7 Jan 2002 Brad Hards and another";
! // We only try to claim CDC Ethernet model devices */
static struct usb_device_id CDCEther_ids[] = {
! { USB_INTERFACE_INFO(USB_CLASS_COMM, 6, 0) },
! { }
};
! /*
! * module parameter that provides an alternate upper limit on the
* number of multicast filters we use, with a default to use all
* the filters available to us. Note that the actual number used
* is the lesser of this parameter and the number returned in the
--- 25,44 ----
#include
#include
#include
#include
! #include
#include "CDCEther.h"
! static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
! /* Take any CDC device, and sort it out in probe() */
static struct usb_device_id CDCEther_ids[] = {
! { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
! { } /* Terminating null entry */
};
! /*
! * module parameter that provides an alternate upper limit on the
* number of multicast filters we use, with a default to use all
* the filters available to us. Note that the actual number used
* is the lesser of this parameter and the number returned in the
***************
*** 54,59 ****
--- 47,53 ----
*/
static int multicast_filter_limit = 32767;
+
//////////////////////////////////////////////////////////////////////////////
// Callback routines from USB device /////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
***************
*** 65,80 ****
int count = urb->actual_length, res;
struct sk_buff *skb;
! switch ( urb->status ) {
! case USB_ST_NOERROR:
! break;
! case USB_ST_URB_KILLED:
! return;
! default:
! dbg("rx status %d", urb->status);
! }
!
! // Sanity check
if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
dbg("BULK IN callback but driver is not active!");
return;
--- 59,65 ----
int count = urb->actual_length, res;
struct sk_buff *skb;
! // Sanity check
if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
dbg("BULK IN callback but driver is not active!");
return;
***************
*** 148,154 ****
// Give this to the USB subsystem so it can tell us
// when more data arrives.
if ( (res = usb_submit_urb(ðer_dev->rx_urb)) ) {
! warn("%s failed submit rx_urb %d", __FUNCTION__, res);
}
// We are no longer busy, show us the frames!!!
--- 133,139 ----
// Give this to the USB subsystem so it can tell us
// when more data arrives.
if ( (res = usb_submit_urb(ðer_dev->rx_urb)) ) {
! warn( __FUNCTION__ " failed submint rx_urb %d", res);
}
// We are no longer busy, show us the frames!!!
***************
*** 175,243 ****
// Hmm... What on Earth could have happened???
if ( urb->status ) {
! dbg("%s: TX status %d", ether_dev->net->name, urb->status);
}
// Update the network interface and tell it we are
// ready for another frame
ether_dev->net->trans_start = jiffies;
netif_wake_queue( ether_dev->net );
-
}
! #if 0
! static void setpktfilter_done( struct urb *urb )
! {
! ether_dev_t *ether_dev = urb->context;
! struct net_device *net;
!
! if ( !ether_dev )
! return;
! dbg("got ctrl callback for setting packet filter");
! switch ( urb->status ) {
! case USB_ST_NOERROR:
! break;
! case USB_ST_URB_KILLED:
! return;
! default:
! dbg("intr status %d", urb->status);
! }
! }
! #endif
!
! static void intr_callback( struct urb *urb )
! {
! ether_dev_t *ether_dev = urb->context;
! struct net_device *net;
! __u8 *d;
!
! if ( !ether_dev )
! return;
! dbg("got intr callback");
! switch ( urb->status ) {
! case USB_ST_NOERROR:
! break;
! case USB_ST_URB_KILLED:
! return;
! default:
! dbg("intr status %d", urb->status);
! }
!
! d = urb->transfer_buffer;
! dbg("d: %x", d[0]);
! net = ether_dev->net;
! if ( d[0] & 0xfc ) {
! ether_dev->stats.tx_errors++;
! if ( d[0] & TX_UNDERRUN )
! ether_dev->stats.tx_fifo_errors++;
! if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
! ether_dev->stats.tx_aborted_errors++;
! if ( d[0] & LATE_COL )
! ether_dev->stats.tx_window_errors++;
! if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
! netif_carrier_off(net);
! }
! }
//////////////////////////////////////////////////////////////////////////////
// Routines for turning net traffic on and off on the USB side ///////////////
--- 160,206 ----
// Hmm... What on Earth could have happened???
if ( urb->status ) {
! info("%s: TX status %d", ether_dev->net->name, urb->status);
}
// Update the network interface and tell it we are
// ready for another frame
ether_dev->net->trans_start = jiffies;
netif_wake_queue( ether_dev->net );
}
! //static void intr_callback( struct urb *urb )
! //{
! // ether_dev_t *ether_dev = urb->context;
! // struct net_device *net;
! // __u8 *d;
! //
! // if ( !ether_dev )
! // return;
! //
! // switch ( urb->status ) {
! // case USB_ST_NOERROR:
! // break;
! // case USB_ST_URB_KILLED:
! // return;
! // default:
! // info("intr status %d", urb->status);
! // }
! //
! // d = urb->transfer_buffer;
! // net = ether_dev->net;
! // if ( d[0] & 0xfc ) {
! // ether_dev->stats.tx_errors++;
! // if ( d[0] & TX_UNDERRUN )
! // ether_dev->stats.tx_fifo_errors++;
! // if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
! // ether_dev->stats.tx_aborted_errors++;
! // if ( d[0] & LATE_COL )
! // ether_dev->stats.tx_window_errors++;
! // if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
! // ether_dev->stats.tx_carrier_errors++;
! // }
! //}
//////////////////////////////////////////////////////////////////////////////
// Routines for turning net traffic on and off on the USB side ///////////////
***************
*** 250,257 ****
// Here would be the time to set the data interface to the configuration where
// it has two endpoints that use a protocol we can understand.
! if (usb_set_interface( usb,
! ether_dev->data_bInterfaceNumber,
ether_dev->data_bAlternateSetting_with_traffic ) ) {
err("usb_set_interface() failed" );
err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
--- 213,220 ----
// Here would be the time to set the data interface to the configuration where
// it has two endpoints that use a protocol we can understand.
! if (usb_set_interface( usb,
! ether_dev->data_bInterfaceNumber,
ether_dev->data_bAlternateSetting_with_traffic ) ) {
err("usb_set_interface() failed" );
err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
***************
*** 267,274 ****
// no endpoints. This is what the spec suggests.
if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
! if (usb_set_interface( ether_dev->usb,
! ether_dev->data_bInterfaceNumber,
ether_dev->data_bAlternateSetting_without_traffic ) ) {
err("usb_set_interface() failed");
}
--- 230,237 ----
// no endpoints. This is what the spec suggests.
if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
! if (usb_set_interface( ether_dev->usb,
! ether_dev->data_bInterfaceNumber,
ether_dev->data_bAlternateSetting_without_traffic ) ) {
err("usb_set_interface() failed");
}
***************
*** 363,371 ****
return 0;
}
- //////////////////////////////////////////////////////////////////////////////
- // Standard routines for kernel Ethernet Device //////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
{
// Easy enough!
--- 326,331 ----
***************
*** 379,413 ****
// Turn on the USB and let the packets flow!!!
if ( (res = enable_net_traffic( ether_dev )) ) {
! err("%s can't enable_net_traffic() - %d", __FUNCTION__, res );
return -EIO;
}
! /* Prep a receive URB */
FILL_BULK_URB( ðer_dev->rx_urb, ether_dev->usb,
usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
! ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
read_bulk_callback, ether_dev );
! /* Put it out there so the device can send us stuff */
! if ( (res = usb_submit_urb(ðer_dev->rx_urb)) ) {
! /* Hmm... Okay... */
! warn( "%s failed rx_urb %d", __FUNCTION__, res );
! }
!
! if (ether_dev->properties & HAVE_NOTIFICATION_ELEMENT) {
! /* Arm and submit the interrupt URB */
! FILL_INT_URB( ðer_dev->intr_urb,
! ether_dev->usb,
! usb_rcvintpipe(ether_dev->usb, ether_dev->comm_ep_in),
! ether_dev->intr_buff,
! 8, /* Transfer buffer length */
! intr_callback,
! ether_dev,
! ether_dev->intr_interval);
! if ( (res = usb_submit_urb(ðer_dev->intr_urb)) ) {
! warn("%s failed intr_urb %d", __FUNCTION__, res );
! }
}
// Tell the kernel we are ready to start receiving from it
--- 339,359 ----
// Turn on the USB and let the packets flow!!!
if ( (res = enable_net_traffic( ether_dev )) ) {
! err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
return -EIO;
}
! // Prep a receive URB
FILL_BULK_URB( ðer_dev->rx_urb, ether_dev->usb,
usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
! ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
read_bulk_callback, ether_dev );
! // Put it out there so the device can send us stuff
! if ( (res = usb_submit_urb(ðer_dev->rx_urb)) )
! {
! // Hmm... Okay...
! warn( __FUNCTION__ " failed rx_urb %d", res );
}
// Tell the kernel we are ready to start receiving from it
***************
*** 440,572 ****
usb_unlink_urb( ðer_dev->rx_urb );
usb_unlink_urb( ðer_dev->tx_urb );
usb_unlink_urb( ðer_dev->intr_urb );
! usb_unlink_urb( ðer_dev->ctrl_urb );
!
// That's it. I'm done.
return 0;
}
- static int netdev_ethtool_ioctl(struct net_device *netdev, void *useraddr)
- {
- ether_dev_t *ether_dev = netdev->priv;
- u32 cmd;
- char tmp[40];
-
- if (get_user(cmd, (u32 *)useraddr))
- return -EFAULT;
-
- switch (cmd) {
- /* get driver info */
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
- strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
- strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
- sprintf(tmp, "usb%d:%d", ether_dev->usb->bus->busnum, ether_dev->usb->devnum);
- strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
- sprintf(tmp, "CDC %x.%x", ((ether_dev->bcdCDC & 0xff00)>>8), (ether_dev->bcdCDC & 0x00ff) );
- strncpy(info.fw_version, tmp, ETHTOOL_BUSINFO_LEN);
- if (copy_to_user(useraddr, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- /* get link status */
- case ETHTOOL_GLINK: {
- struct ethtool_value edata = {ETHTOOL_GLINK};
- edata.data = netif_carrier_ok(netdev);
- if (copy_to_user(useraddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
- }
- }
- dbg("Got unsupported ioctl: %x", cmd);
- return -EOPNOTSUPP; /* the ethtool user space tool relies on this */
- }
-
static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
{
switch(cmd) {
! case SIOCETHTOOL:
! return netdev_ethtool_ioctl(net, (void *) rq->ifr_data);
! default:
! return -ENOTTY; /* per ioctl man page */
}
}
- /* Multicast routines */
-
static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
{
! #if 0
! struct usb_ctrlrequest *dr = ðer_dev->ctrl_dr;
! int res;
!
! dr->bRequestType = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE;
! dr->bRequest = SET_ETHERNET_PACKET_FILTER;
! dr->wValue = cpu_to_le16(ether_dev->mode_flags);
! dr->wIndex = cpu_to_le16((u16)ether_dev->comm_interface);
! dr->wLength = 0;
!
! FILL_CONTROL_URB(ðer_dev->ctrl_urb,
! ether_dev->usb,
usb_sndctrlpipe(ether_dev->usb, 0),
! dr,
! NULL,
NULL,
! setpktfilter_done,
! ether_dev);
! if ( (res = usb_submit_urb(ðer_dev->ctrl_urb)) ) {
! warn("%s failed submit ctrl_urb %d", __FUNCTION__, res);
! }
! #endif
- }
static void CDCEther_set_multicast( struct net_device *net )
{
ether_dev_t *ether_dev = net->priv;
int i;
__u8 *buff;
// Tell the kernel to stop sending us frames while we get this
// all set up.
netif_stop_queue(net);
! /* Note: do not reorder, GCC is clever about common statements. */
! if (net->flags & IFF_PROMISC) {
! /* Unconditionally log net taps. */
! dbg( "%s: Promiscuous mode enabled", net->name);
ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
! } else if (net->mc_count > ether_dev->wNumberMCFilters) {
! /* Too many to filter perfectly -- accept all multicasts. */
! dbg("%s: too many MC filters for hardware, using allmulti", net->name);
ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
} else if (net->flags & IFF_ALLMULTI) {
! /* Filter in software */
! dbg("%s: using allmulti", net->name);
ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
! } else {
/* do multicast filtering in hardware */
! struct dev_mc_list *mclist;
! dbg("%s: set multicast filters", net->name);
ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
! for (i = 0, mclist = net->mc_list;
! mclist && i < net->mc_count;
! i++, mclist = mclist->next) {
! memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
}
#if 0
usb_control_msg(ether_dev->usb,
--- 386,477 ----
usb_unlink_urb( ðer_dev->rx_urb );
usb_unlink_urb( ðer_dev->tx_urb );
usb_unlink_urb( ðer_dev->intr_urb );
!
// That's it. I'm done.
return 0;
}
static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
{
+ //__u16 *data = (__u16 *)&rq->ifr_data;
+ //ether_dev_t *ether_dev = net->priv;
+
+ // No support here yet.
+ // Do we need support???
switch(cmd) {
! case SIOCDEVPRIVATE:
! return -EOPNOTSUPP;
! case SIOCDEVPRIVATE+1:
! return -EOPNOTSUPP;
! case SIOCDEVPRIVATE+2:
! //return 0;
! return -EOPNOTSUPP;
! default:
! return -EOPNOTSUPP;
}
}
static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
{
! usb_control_msg(ether_dev->usb,
usb_sndctrlpipe(ether_dev->usb, 0),
! SET_ETHERNET_PACKET_FILTER, /* request */
! USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
! cpu_to_le16(ether_dev->mode_flags), /* value */
! cpu_to_le16((u16)ether_dev->comm_interface), /* index */
NULL,
! 0, /* size */
! HZ); /* timeout */
! }
static void CDCEther_set_multicast( struct net_device *net )
{
ether_dev_t *ether_dev = net->priv;
int i;
__u8 *buff;
+
// Tell the kernel to stop sending us frames while we get this
// all set up.
netif_stop_queue(net);
! /* Note: do not reorder, GCC is clever about common statements. */
! if (net->flags & IFF_PROMISC) {
! /* Unconditionally log net taps. */
! info( "%s: Promiscuous mode enabled", net->name);
ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
! } else if (net->mc_count > ether_dev->wNumberMCFilters) {
! /* Too many to filter perfectly -- accept all multicasts. */
! info("%s: set too many MC filters, using allmulti", net->name);
ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
} else if (net->flags & IFF_ALLMULTI) {
! /* Filter in software */
! info("%s: using allmulti", net->name);
ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
! } else {
/* do multicast filtering in hardware */
! struct dev_mc_list *mclist;
! info("%s: set multicast filters", net->name);
ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
! for (i = 0, mclist = net->mc_list;
! mclist && i < net->mc_count;
! i++, mclist = mclist->next) {
! memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
}
#if 0
usb_control_msg(ether_dev->usb,
***************
*** 582,590 ****
kfree(buff);
}
CDC_SetEthernetPacketFilter(ether_dev);
!
! /* Tell the kernel to start giving frames to us again. */
netif_wake_queue(net);
}
--- 487,496 ----
kfree(buff);
}
+ #if 0
CDC_SetEthernetPacketFilter(ether_dev);
! #endif
! // Tell the kernel to start giving frames to us again.
netif_wake_queue(net);
}
***************
*** 592,633 ****
// Routines used to parse out the Functional Descriptors /////////////////////
//////////////////////////////////////////////////////////////////////////////
! /* Header Descriptor - CDC Spec 5.2.3.1, Table 26 */
! static int parse_header_functional_descriptor( int *bFunctionLength,
! int bDescriptorType,
int bDescriptorSubtype,
unsigned char *data,
ether_dev_t *ether_dev,
int *requirements )
{
! /* Check to make sure we haven't seen one of these already. */
if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
err( "Multiple Header Functional Descriptors found." );
return -1;
}
!
! /* Check for appropriate length */
! if (*bFunctionLength != HEADER_FUNC_DESC_LEN) {
! dbg( "Invalid length in Header Functional Descriptor, working around it." );
! /* This is a hack to get around a particular device (NO NAMES)
! * It has this function length set to the length of the
! * whole class-specific descriptor */
! *bFunctionLength = HEADER_FUNC_DESC_LEN;
}
! /* Nothing extremely useful here */
! /* We'll keep it for posterity */
ether_dev->bcdCDC = data[0] + (data[1] << 8);
! dbg( "Found Header descriptor, CDC version %x.", ether_dev->bcdCDC);
! /* We've seen one of these */
*requirements &= ~REQ_HDR_FUNC_DESCR;
!
! /* Success */
return 0;
}
- /* Union Descriptor - CDC Spec 5.2.3.8, Table 33 */
static int parse_union_functional_descriptor( int *bFunctionLength,
int bDescriptorType,
int bDescriptorSubtype,
--- 498,537 ----
// Routines used to parse out the Functional Descriptors /////////////////////
//////////////////////////////////////////////////////////////////////////////
! static int parse_header_functional_descriptor( int *bFunctionLength,
! int bDescriptorType,
int bDescriptorSubtype,
unsigned char *data,
ether_dev_t *ether_dev,
int *requirements )
{
! // Check to make sure we haven't seen one of these already.
if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
err( "Multiple Header Functional Descriptors found." );
return -1;
}
!
! // Is it the right size???
! if (*bFunctionLength != 5) {
! info( "Invalid length in Header Functional Descriptor" );
! // This is a hack to get around a particular device (NO NAMES)
! // It has this function length set to the length of the
! // whole class-specific descriptor
! *bFunctionLength = 5;
}
! // Nothing extremely useful here.
! // We'll keep it for posterity
ether_dev->bcdCDC = data[0] + (data[1] << 8);
! dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
! // We've seen one of these
*requirements &= ~REQ_HDR_FUNC_DESCR;
!
! // It's all good.
return 0;
}
static int parse_union_functional_descriptor( int *bFunctionLength,
int bDescriptorType,
int bDescriptorSubtype,
***************
*** 635,723 ****
ether_dev_t *ether_dev,
int *requirements )
{
! /* Check to make sure we haven't seen one of these already. */
if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
err( "Multiple Union Functional Descriptors found." );
return -1;
}
! /* Check for appropriate length */
! if (*bFunctionLength != UNION_FUNC_DESC_LEN) {
// It is NOT the size we expected.
! err( "Invalid length in Union Functional Descriptor." );
return -1;
}
! /* Sanity check of sorts */
if (ether_dev->comm_interface != data[0]) {
! /* This tells us that we are chasing the wrong comm
! * interface or we are crazy or something else weird. */
if (ether_dev->comm_interface == data[1]) {
! dbg( "Probably broken Union descriptor, fudging data interface." );
! /* We'll need this in a few microseconds,
! * so if the comm interface was the first slave,
! * then probably the master interface is the data one
! * Just hope for the best */
ether_dev->data_interface = data[0];
} else {
! err( "Union Functional Descriptor is broken beyond repair." );
return -1;
}
! } else{ /* Descriptor is OK */
ether_dev->data_interface = data[1];
}
! /* We've seen one of these */
*requirements &= ~REQ_UNION_FUNC_DESCR;
!
! /* Success */
return 0;
}
! /* Ethernet Descriptor - CDC Spec 5.2.3.16, Table 41 */
! static int parse_ethernet_functional_descriptor( int *bFunctionLength,
int bDescriptorType,
int bDescriptorSubtype,
unsigned char *data,
ether_dev_t *ether_dev,
int *requirements )
{
! //* Check to make sure we haven't seen one of these already. */
if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
err( "Multiple Ethernet Functional Descriptors found." );
return -1;
}
! /* Check for appropriate length */
! if (*bFunctionLength != ETHERNET_FUNC_DESC_LEN) {
! err( "Invalid length in Ethernet Networking Functional Descriptor." );
return -1;
}
!
! /* Lots of goodies from this one. They are all important. */
ether_dev->iMACAddress = data[0];
ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
! ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8));
! if (ether_dev->wNumberMCFilters & (1 << 15)) {
! ether_dev->properties |= PERFECT_FILTERING;
! dbg("Perfect filtering support");
! } else {
! dbg("Imperfect filtering support - need sw hashing");
! }
! if (0 == (ether_dev->wNumberMCFilters & (0x7f))) {
! ether_dev->properties |= NO_SET_MULTICAST;
! dbg("Can't use SetEthernetMulticastFilters request");
! }
if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
ether_dev->wNumberMCFilters = multicast_filter_limit;
! }
ether_dev->bNumberPowerFilters = data[9];
! /* We've seen one of these */
*requirements &= ~REQ_ETH_FUNC_DESCR;
!
! /* Success */
return 0;
}
--- 539,615 ----
ether_dev_t *ether_dev,
int *requirements )
{
! // Check to make sure we haven't seen one of these already.
if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
err( "Multiple Union Functional Descriptors found." );
return -1;
}
! // Is it the right size?
! if (*bFunctionLength != 5) {
// It is NOT the size we expected.
! err( "Unsupported length in Union Functional Descriptor" );
return -1;
}
! // Sanity check of sorts
if (ether_dev->comm_interface != data[0]) {
! // This tells us that we are chasing the wrong comm
! // interface or we are crazy or something else weird.
if (ether_dev->comm_interface == data[1]) {
! info( "Probably broken Union descriptor, fudging data interface" );
! // We'll need this in a few microseconds,
! // so guess here, and hope for the best
ether_dev->data_interface = data[0];
} else {
! err( "Union Functional Descriptor is broken beyond repair" );
return -1;
}
! } else{ // Descriptor is OK
! // We'll need this in a few microseconds!
ether_dev->data_interface = data[1];
}
! // We've seen one of these now.
*requirements &= ~REQ_UNION_FUNC_DESCR;
!
! // Done
return 0;
}
! static int parse_ethernet_functional_descriptor( int *bFunctionLength,
int bDescriptorType,
int bDescriptorSubtype,
unsigned char *data,
ether_dev_t *ether_dev,
int *requirements )
{
! // Check to make sure we haven't seen one of these already.
if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
err( "Multiple Ethernet Functional Descriptors found." );
return -1;
}
! // Is it the right size?
! if (*bFunctionLength != 13) {
! err( "Invalid length in Ethernet Networking Functional Descriptor" );
return -1;
}
!
! // Lots of goodies from this one. They are all important.
ether_dev->iMACAddress = data[0];
ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
! ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
ether_dev->wNumberMCFilters = multicast_filter_limit;
! }
ether_dev->bNumberPowerFilters = data[9];
! // We've seen one of these now.
*requirements &= ~REQ_ETH_FUNC_DESCR;
!
! // That's all she wrote.
return 0;
}
***************
*** 728,742 ****
ether_dev_t *ether_dev,
int *requirements )
{
! /* There should only be one type if we are sane */
if (bDescriptorType != CS_INTERFACE) {
! err( "Invalid bDescriptorType found." );
return -1;
}
! /* The Subtype tells the tale - CDC spec Table 25 */
! switch (bDescriptorSubtype) {
! case 0x00: /* Header Functional Descriptor */
return parse_header_functional_descriptor( bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
--- 620,634 ----
ether_dev_t *ether_dev,
int *requirements )
{
! // There should only be one type if we are sane
if (bDescriptorType != CS_INTERFACE) {
! info( "Invalid bDescriptorType found." );
return -1;
}
! // The Subtype tells the tale.
! switch (bDescriptorSubtype){
! case 0x00: // Header Functional Descriptor
return parse_header_functional_descriptor( bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
***************
*** 744,750 ****
ether_dev,
requirements );
break;
! case 0x06: /* Union Functional Descriptor */
return parse_union_functional_descriptor( bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
--- 636,642 ----
ether_dev,
requirements );
break;
! case 0x06: // Union Functional Descriptor
return parse_union_functional_descriptor( bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
***************
*** 752,758 ****
ether_dev,
requirements );
break;
! case 0x0F: /* Ethernet Networking Functional Descriptor */
return parse_ethernet_functional_descriptor( bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
--- 644,650 ----
ether_dev,
requirements );
break;
! case 0x0F: // Ethernet Networking Functional Descriptor
return parse_ethernet_functional_descriptor( bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
***************
*** 760,771 ****
ether_dev,
requirements );
break;
! default: /* We don't support this at this time... */
! /* However that doesn't necessarily indicate an error. */
! dbg( "Unexpected header type %x.", bDescriptorSubtype );
return 0;
}
! /* How did we get here? */
return -1;
}
--- 652,663 ----
ether_dev,
requirements );
break;
! default: // We don't support this at this time...
! // However that doesn't necessarily indicate an error.
! dbg( "Unexpected header type %x:", bDescriptorSubtype );
return 0;
}
! // How did we get here???
return -1;
}
***************
*** 776,824 ****
int bFunctionLength;
int bDescriptorType;
int bDescriptorSubtype;
! int requirements = REQUIREMENTS_TOTAL; /* We init to our needs, and then clear
! * bits as we find the descriptors */
! /* As long as there is something here, we will try to parse it */
! /* All of the functional descriptors start with the same 3 byte pattern */
while (loc < length) {
! /* Length */
bFunctionLength = data[loc];
loc++;
!
! /* Type */
bDescriptorType = data[loc];
loc++;
!
! /* Subtype */
bDescriptorSubtype = data[loc];
loc++;
! /* ship this off to be processed */
rc = parse_protocol_unit_functional_descriptor( &bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
&data[loc],
ether_dev,
&requirements );
! /* Did it process okay? */
if (rc) {
! /* Something was hosed somewhere. */
! /* No need to continue */
err("Bad descriptor parsing: %x", rc );
return -1;
}
! /* We move the loc pointer along, remembering
! * that we have already taken three bytes */
loc += (bFunctionLength - 3);
}
! /* Check to see if we got everything we need. */
if (requirements) {
// We missed some of the requirements...
! err( "Not all required functional descriptors present 0x%08X.", requirements );
return -1;
}
! /* We got everything */
return 0;
}
--- 668,713 ----
int bFunctionLength;
int bDescriptorType;
int bDescriptorSubtype;
! int requirements = REQUIREMENTS_TOTAL;
! // As long as there is something here, we will try to parse it
while (loc < length) {
! // Length
bFunctionLength = data[loc];
loc++;
!
! // Type
bDescriptorType = data[loc];
loc++;
!
! // Subtype
bDescriptorSubtype = data[loc];
loc++;
! // ship this off to be processed elsewhere.
rc = parse_protocol_unit_functional_descriptor( &bFunctionLength,
bDescriptorType,
bDescriptorSubtype,
&data[loc],
ether_dev,
&requirements );
! // Did it process okay?
if (rc) {
! // Something was hosed somewhere.
! // No need to continue;
err("Bad descriptor parsing: %x", rc );
return -1;
}
! // We have already taken three bytes.
loc += (bFunctionLength - 3);
}
! // Check to see if we got everything we need.
if (requirements) {
// We missed some of the requirements...
! err( "Not all required functional descriptors present 0x%08X", requirements );
return -1;
}
! // We got everything.
return 0;
}
***************
*** 832,859 ****
struct usb_interface *comm_intf_group = NULL;
struct usb_interface_descriptor *comm_intf = NULL;
int rc = -1;
! /* The assumption here is that find_ethernet_comm_interface
! * and find_valid_configuration
! * have already filled in the information about where to find
! * the a valid commication interface. */
conf = &( device->config[ether_dev->configuration_num] );
comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
- /* Let's check and see if it has the extra information we need */
if (comm_intf->extralen > 0) {
! /* This is where the information is SUPPOSED to be */
rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
} else if (conf->extralen > 0) {
! /* This is a hack. The spec says it should be at the interface
! * location checked above. However I have seen it here also.
! * This is the same device that requires the functional descriptor hack above */
! dbg( "Ethernet information found at device configuration. Trying to use it anyway." );
rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
} else {
! /* I don't know where else to look */
! err( "No ethernet information found." );
rc = -1;
}
return rc;
--- 721,748 ----
struct usb_interface *comm_intf_group = NULL;
struct usb_interface_descriptor *comm_intf = NULL;
int rc = -1;
! // The assumption here is that find_ethernet_comm_interface
! // and find_valid_configuration
! // have already filled in the information about where to find
! // the a valid commication interface.
conf = &( device->config[ether_dev->configuration_num] );
comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
+ // Let's check and see if it has the extra information we need...
if (comm_intf->extralen > 0) {
! // This is where the information is SUPPOSED to be.
rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
} else if (conf->extralen > 0) {
! // This is a hack. The spec says it should be at the interface
! // location checked above. However I have seen it here also.
! // This is the same device that requires the functional descriptor hack above
! warn( "Ethernet information found at device configuration. This is broken." );
rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
} else {
! // I don't know where else to look.
! warn( "No ethernet information found." );
rc = -1;
}
return rc;
***************
*** 868,910 ****
struct usb_config_descriptor *conf = NULL;
struct usb_interface *data_intf_group = NULL;
struct usb_interface_descriptor *data_intf = NULL;
!
! /* Walk through and get to the data interface we are checking. */
conf = &( device->config[ether_dev->configuration_num] );
data_intf_group = &( conf->interface[ether_dev->data_interface] );
data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
! /* Start out assuming we won't find anything we can use */
ether_dev->data_ep_in = 0;
ether_dev->data_ep_out = 0;
!
! /* If these are not BULK endpoints, we don't want them */
! if ( data_intf->endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK ) {
return -1;
! }
! if ( data_intf->endpoint[1].bmAttributes != USB_ENDPOINT_XFER_BULK ) {
return -1;
}
! /* Check the first endpoint to see if it is IN or OUT */
! if ( data_intf->endpoint[0].bEndpointAddress & USB_DIR_IN ) {
ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
} else {
! ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress;
ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
}
! /* Check the second endpoint to see if it is IN or OUT */
! if ( data_intf->endpoint[1].bEndpointAddress & USB_DIR_IN ) {
ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
} else {
! ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress;
ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
}
!
! /* Now make sure we got both an IN and an OUT */
if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
! dbg( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
return 0;
}
return -1;
--- 757,803 ----
struct usb_config_descriptor *conf = NULL;
struct usb_interface *data_intf_group = NULL;
struct usb_interface_descriptor *data_intf = NULL;
!
! // Walk through and get to the data interface we are checking.
conf = &( device->config[ether_dev->configuration_num] );
data_intf_group = &( conf->interface[ether_dev->data_interface] );
data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
! // Start out assuming we won't find anything we can use
ether_dev->data_ep_in = 0;
ether_dev->data_ep_out = 0;
!
! // If these are not BULK endpoints, we don't want them
! if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
return -1;
! } if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
return -1;
}
! // Check the first endpoint to see if it is IN or OUT
! if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
! // This endpoint is IN
ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
} else {
! // This endpoint is OUT
! ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;
ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
}
! // Check the second endpoint to see if it is IN or OUT
! if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
! // This endpoint is IN
ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
} else {
! // This endpoint is OUT
! ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;
ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
}
!
! // Now make sure we got both an IN and an OUT
if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
! // We did get both, we are in good shape...
! info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
return 0;
}
return -1;
***************
*** 994,1038 ****
for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
comm_intf = &( comm_intf_group->altsetting[altset_num] );
! /* Good, we found one, we will try this one */
! /* Fill in the structure */
! ether_dev->comm_interface = intf_num;
! ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
! ether_dev->comm_interface_altset_num = altset_num;
! ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
!
! // Look for the Ethernet Functional Descriptors
! rc = find_and_parse_ethernet_class_information( device, ether_dev );
! if (rc) {
! // Nope this was no good after all.
! continue;
! }
!
! /* Check that we really can talk to the data interface
! * This includes # of endpoints, protocols, etc. */
! rc = verify_ethernet_data_interface( device, ether_dev );
! if (rc) {
! /* We got something we didn't like */
! continue;
! }
! /* It is a bit ambiguous whether the Ethernet model really requires
! * the notification element (usually an interrupt endpoint) or not
! * And some products (eg Sharp Zaurus) don't support it, so we
! * only use the notification element if present */
! /* We check for a sane endpoint before using it */
! if ( (comm_intf->bNumEndpoints == 1) &&
! (comm_intf->endpoint[0].bEndpointAddress & USB_DIR_IN) &&
! (comm_intf->endpoint[0].bmAttributes == USB_ENDPOINT_XFER_INT)) {
! ether_dev->properties |= HAVE_NOTIFICATION_ELEMENT;
! ether_dev->comm_ep_in = (comm_intf->endpoint[0].bEndpointAddress & 0x7F);
! dbg("interrupt address: %x",ether_dev->comm_ep_in);
! ether_dev->intr_interval = (comm_intf->endpoint[0].bInterval);
! dbg("interrupt interval: %d",ether_dev->intr_interval);
! }
! // This communication interface seems to give us everything
! // we require. We have all the ethernet info we need.
!
! return 0;
} // end for altset_num
} // end for intf_num
return -1;
--- 887,931 ----
for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
comm_intf = &( comm_intf_group->altsetting[altset_num] );
! // Is this a communication class of interface of the
! // ethernet subclass variety.
! if ( ( comm_intf->bInterfaceClass == 0x02 )
! && ( comm_intf->bInterfaceSubClass == 0x06 )
! && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
! if ( comm_intf->bNumEndpoints == 1 ) {
! // Good, we found one, we will try this one
! // Fill in the structure...
! ether_dev->comm_interface = intf_num;
! ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
! ether_dev->comm_interface_altset_num = altset_num;
! ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
!
! // Look for the Ethernet Functional Descriptors
! rc = find_and_parse_ethernet_class_information( device, ether_dev );
! if (rc) {
! // Nope this was no good after all.
! continue;
! }
!
! // Check that we really can talk to the data
! // interface
! // This includes # of endpoints, protocols,
! // etc.
! rc = verify_ethernet_data_interface( device, ether_dev );
! if (rc) {
! // We got something we didn't like
! continue;
! }
! // This communication interface seems to give us everything
! // we require. We have all the ethernet info we need.
! // Let's get out of here and go home right now.
! return 0;
! } else {
! // bNumEndPoints != 1
! // We found an interface that had the wrong number of
! // endpoints but would have otherwise been okay
! } // end bNumEndpoints check.
! } // end interface specifics check.
} // end for altset_num
} // end for intf_num
return -1;
***************
*** 1112,1119 ****
static inline unsigned char hex2dec( unsigned char digit )
{
! /* Is there a standard way to do this??? */
! /* I have written this code TOO MANY times. */
if ( (digit >= '0') && (digit <= '9') ) {
return (digit - '0');
}
--- 1005,1012 ----
static inline unsigned char hex2dec( unsigned char digit )
{
! // Is there a standard way to do this???
! // I have written this code TOO MANY times.
if ( (digit >= '0') && (digit <= '9') ) {
return (digit - '0');
}
***************
*** 1123,1136 ****
if ( (digit >= 'A') && (digit <= 'F') ) {
return (digit - 'A' + 10);
}
! return 16;
}
- /* CDC Ethernet devices provide the MAC address as a string */
- /* We get an index to the string in the Ethernet functional header */
- /* This routine retrieves the string, sanity checks it, and sets the */
- /* MAC address in the network device */
- /* The encoding is a bit wacky - see CDC Spec Table 41 for details */
static void set_ethernet_addr( ether_dev_t *ether_dev )
{
unsigned char mac_addr[6];
--- 1016,1024 ----
if ( (digit >= 'A') && (digit <= 'F') ) {
return (digit - 'A' + 10);
}
! return 0;
}
static void set_ethernet_addr( ether_dev_t *ether_dev )
{
unsigned char mac_addr[6];
***************
*** 1138,1144 ****
int len;
unsigned char buffer[13];
! /* Let's assume we don't get anything */
mac_addr[0] = 0x00;
mac_addr[1] = 0x00;
mac_addr[2] = 0x00;
--- 1026,1032 ----
int len;
unsigned char buffer[13];
! // Let's assume we don't get anything...
mac_addr[0] = 0x00;
mac_addr[1] = 0x00;
mac_addr[2] = 0x00;
***************
*** 1146,1175 ****
mac_addr[4] = 0x00;
mac_addr[5] = 0x00;
! /* Let's ask the device */
! if (0 > (len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13))) {
! err("Attempting to get MAC address failed: %d", -1*len);
! return;
! }
! /* Sanity check */
if (len != 12) {
! /* You gotta love failing sanity checks */
err("Attempting to get MAC address returned %d bytes", len);
return;
}
! /* Fill in the mac_addr */
for (i = 0; i < 6; i++) {
! if ((16 == buffer[2 * i]) || (16 == buffer[2 * i + 1])) {
! err("Bad value in MAC address");
! }
! else {
! mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
! }
}
! /* Now copy it over to our network device structure */
memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
}
--- 1034,1055 ----
mac_addr[4] = 0x00;
mac_addr[5] = 0x00;
! // Let's ask the device...
! len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
! // Sanity check!
if (len != 12) {
! // You gotta love failing sanity checks
err("Attempting to get MAC address returned %d bytes", len);
return;
}
! // Fill in the mac_addr
for (i = 0; i < 6; i++) {
! mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
}
! // Now copy it over to the kernel's network driver.
memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
}
***************
*** 1187,1198 ****
unsigned char sern[256];
unsigned char *mac_addr;
! /* Default empty strings in case we don't find a real one */
manu[0] = 0x00;
prod[0] = 0x00;
sern[0] = 0x00;
! /* Try to get the device Manufacturer */
string_num = ether_dev->usb->descriptor.iManufacturer;
if (string_num) {
// Put it into its buffer
--- 1067,1078 ----
unsigned char sern[256];
unsigned char *mac_addr;
! // Default empty strings in case we don't find a real one
manu[0] = 0x00;
prod[0] = 0x00;
sern[0] = 0x00;
! // Try to get the device Manufacturer
string_num = ether_dev->usb->descriptor.iManufacturer;
if (string_num) {
// Put it into its buffer
***************
*** 1201,1207 ****
manu[len] = 0x00;
}
! /* Try to get the device Product Name */
string_num = ether_dev->usb->descriptor.iProduct;
if (string_num) {
// Put it into its buffer
--- 1081,1087 ----
manu[len] = 0x00;
}
! // Try to get the device Product Name
string_num = ether_dev->usb->descriptor.iProduct;
if (string_num) {
// Put it into its buffer
***************
*** 1210,1216 ****
prod[len] = 0x00;
}
! /* Try to get the device Serial Number */
string_num = ether_dev->usb->descriptor.iSerialNumber;
if (string_num) {
// Put it into its buffer
--- 1090,1096 ----
prod[len] = 0x00;
}
! // Try to get the device Serial Number
string_num = ether_dev->usb->descriptor.iSerialNumber;
if (string_num) {
// Put it into its buffer
***************
*** 1219,1238 ****
sern[len] = 0x00;
}
! /* This makes it easier for us to print */
mac_addr = ether_dev->net->dev_addr;
! /* Now send everything we found to the syslog */
! info( "%s: %s %s %s", ether_dev->net->name, manu, prod, sern);
! dbg( "%s: %02X:%02X:%02X:%02X:%02X:%02X",
! ether_dev->net->name,
! mac_addr[0],
! mac_addr[1],
! mac_addr[2],
! mac_addr[3],
! mac_addr[4],
! mac_addr[5] );
!
}
/* Forward declaration */
--- 1099,1112 ----
sern[len] = 0x00;
}
! // This makes it easier for us to print
mac_addr = ether_dev->net->dev_addr;
! // Now send everything we found to the syslog
! info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X",
! ether_dev->net->name, manu, prod, sern, mac_addr[0],
! mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4],
! mac_addr[5] );
}
/* Forward declaration */
***************
*** 1353,1359 ****
// Send a message to syslog about what we are handling
log_device_info( ether_dev );
! /* We need to manually claim the data interface, while the comm interface gets claimed in the return */
usb_driver_claim_interface( &CDCEther_driver,
&(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]),
ether_dev );
--- 1227,1237 ----
// Send a message to syslog about what we are handling
log_device_info( ether_dev );
! // I claim this interface to be a CDC Ethernet Networking device
! usb_driver_claim_interface( &CDCEther_driver,
! &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]),
! ether_dev );
! // I claim this interface to be a CDC Ethernet Networking device
usb_driver_claim_interface( &CDCEther_driver,
&(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]),
ether_dev );
***************
*** 1361,1368 ****
// Does this REALLY do anything???
usb_inc_dev_use( usb );
// Okay, we are finally done...
! return ether_dev;
}
--- 1239,1249 ----
// Does this REALLY do anything???
usb_inc_dev_use( usb );
+ // TODO - last minute HACK
+ ether_dev->comm_ep_in = 5;
+
// Okay, we are finally done...
! return NULL;
}
***************
*** 1432,1438 ****
int __init CDCEther_init(void)
{
! dbg( "%s", version );
return usb_register( &CDCEther_driver );
}
--- 1313,1319 ----
int __init CDCEther_init(void)
{
! info( "%s", version );
return usb_register( &CDCEther_driver );
}
***************
*** 1452,1461 ****
MODULE_DESCRIPTION("USB CDC Ethernet driver");
MODULE_LICENSE("GPL");
- MODULE_DEVICE_TABLE (usb, CDCEther_ids);
MODULE_PARM (multicast_filter_limit, "i");
MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
//////////////////////////////////////////////////////////////////////////////
// End of file ///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
--- 1333,1343 ----
MODULE_DESCRIPTION("USB CDC Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_PARM (multicast_filter_limit, "i");
MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
+ MODULE_DEVICE_TABLE (usb, CDCEther_ids);
+
//////////////////////////////////////////////////////////////////////////////
// End of file ///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/CDCEther.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/CDCEther.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/CDCEther.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/CDCEther.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,4 ****
! // Portions of this file taken from
// Petko Manolov - Petkan (petkan@dce.bg)
// from his driver pegasus.h
--- 1,4 ----
! // Portions of this file taken from
// Petko Manolov - Petkan (petkan@dce.bg)
// from his driver pegasus.h
***************
*** 18,29 ****
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
! /* From CDC Spec Table 24 */
#define CS_INTERFACE 0x24
#define CDC_ETHER_MAX_MTU 1536
- /* These definitions are used with the ether_dev_t flags element */
#define CDC_ETHER_PRESENT 0x00000001
#define CDC_ETHER_RUNNING 0x00000002
#define CDC_ETHER_TX_BUSY 0x00000004
--- 18,28 ----
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
!
#define CS_INTERFACE 0x24
#define CDC_ETHER_MAX_MTU 1536
#define CDC_ETHER_PRESENT 0x00000001
#define CDC_ETHER_RUNNING 0x00000002
#define CDC_ETHER_TX_BUSY 0x00000004
***************
*** 32,41 ****
#define CDC_ETHER_TX_TIMEOUT (HZ*10)
! #define TX_UNDERRUN 0x80
#define EXCESSIVE_COL 0x40
! #define LATE_COL 0x20
! #define NO_CARRIER 0x10
#define LOSS_CARRIER 0x08
#define JABBER_TIMEOUT 0x04
--- 31,40 ----
#define CDC_ETHER_TX_TIMEOUT (HZ*10)
! #define TX_UNDERRUN 0x80
#define EXCESSIVE_COL 0x40
! #define LATE_COL 0x20
! #define NO_CARRIER 0x10
#define LOSS_CARRIER 0x08
#define JABBER_TIMEOUT 0x04
***************
*** 44,56 ****
#define CDC_ETHER_REQ_GET_REGS 0xf0
#define CDC_ETHER_REQ_SET_REGS 0xf1
#define CDC_ETHER_REQ_SET_REG PIPERIDER_REQ_SET_REGS
typedef struct _ether_dev_t {
struct usb_device *usb;
struct net_device *net;
struct net_device_stats stats;
unsigned flags;
- unsigned properties;
int configuration_num;
int bConfigurationValue;
int comm_interface;
--- 43,64 ----
#define CDC_ETHER_REQ_GET_REGS 0xf0
#define CDC_ETHER_REQ_SET_REGS 0xf1
#define CDC_ETHER_REQ_SET_REG PIPERIDER_REQ_SET_REGS
+ #define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES)))
+
+ #define MODE_FLAG_PROMISCUOUS (1<<0)
+ #define MODE_FLAG_ALL_MULTICAST (1<<1)
+ #define MODE_FLAG_DIRECTED (1<<2)
+ #define MODE_FLAG_BROADCAST (1<<3)
+ #define MODE_FLAG_MULTICAST (1<<4)
+
+ #define SET_ETHERNET_MULTICAST_FILTER 0x40
+ #define SET_ETHERNET_PACKET_FILTER 0x43
typedef struct _ether_dev_t {
struct usb_device *usb;
struct net_device *net;
struct net_device_stats stats;
unsigned flags;
int configuration_num;
int bConfigurationValue;
int comm_interface;
***************
*** 71,114 ****
__u8 iMACAddress;
__u32 bmEthernetStatistics;
__u16 wMaxSegmentSize;
__u16 wNumberMCFilters;
__u8 bNumberPowerFilters;
- __u16 mode_flags;
int intr_interval;
! struct usb_ctrlrequest ctrl_dr;
! struct urb rx_urb, tx_urb, intr_urb, ctrl_urb;
! unsigned char rx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES)));
! unsigned char tx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES)));
! unsigned char intr_buff[8] __attribute__((aligned(L1_CACHE_BYTES))) ;
} ether_dev_t;
- /* These definitions used in the Ethernet Packet Filtering requests */
- /* See CDC Spec Table 62 */
- #define MODE_FLAG_PROMISCUOUS (1<<0)
- #define MODE_FLAG_ALL_MULTICAST (1<<1)
- #define MODE_FLAG_DIRECTED (1<<2)
- #define MODE_FLAG_BROADCAST (1<<3)
- #define MODE_FLAG_MULTICAST (1<<4)
-
- /* CDC Spec class requests - CDC Spec Table 46 */
- #define SET_ETHERNET_MULTICAST_FILTER 0x40
- #define SET_ETHERNET_PACKET_FILTER 0x43
-
-
- /* These definitions are used with the ether_dev_t properties field */
- #define HAVE_NOTIFICATION_ELEMENT 0x0001
- #define PERFECT_FILTERING 0x0002
- #define NO_SET_MULTICAST 0x0004
-
- /* These definitions are used in the requirements parser */
#define REQ_HDR_FUNC_DESCR 0x0001
#define REQ_UNION_FUNC_DESCR 0x0002
#define REQ_ETH_FUNC_DESCR 0x0004
! #define REQUIREMENTS_TOTAL REQ_ETH_FUNC_DESCR | REQ_UNION_FUNC_DESCR | REQ_HDR_FUNC_DESCR
- /* Some useful lengths */
- #define HEADER_FUNC_DESC_LEN 0x5
- #define UNION_FUNC_DESC_LEN 0x5
- #define ETHERNET_FUNC_DESC_LEN 0xD /* 13 for all you decimal weenies */
--- 79,98 ----
__u8 iMACAddress;
__u32 bmEthernetStatistics;
__u16 wMaxSegmentSize;
+ __u16 mode_flags;
__u16 wNumberMCFilters;
__u8 bNumberPowerFilters;
int intr_interval;
! struct urb rx_urb, tx_urb, intr_urb;
! unsigned char ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
! unsigned char ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
! unsigned char ALIGN(intr_buff[8]);
} ether_dev_t;
#define REQ_HDR_FUNC_DESCR 0x0001
#define REQ_UNION_FUNC_DESCR 0x0002
#define REQ_ETH_FUNC_DESCR 0x0004
! #define REQUIREMENTS_TOTAL 0x0007
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/Config.in LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/Config.in
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/Config.in 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/Config.in 2004-05-24 17:35:29.000000000 +0900
***************
*** 4,14 ****
mainmenu_option next_comment
comment 'USB support'
! dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
bool ' USB verbose debug messages' CONFIG_USB_DEBUG
! comment 'Miscellaneous USB options'
bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
--- 4,22 ----
mainmenu_option next_comment
comment 'USB support'
! # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
! # MPC850/MPC823 processors also have a non-PCI USB controller.
! if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" \
! -o "$CONFIG_8xx" = "y" ]; then
! tristate 'Support for USB' CONFIG_USB
! else
! define_bool CONFIG_USB n
! fi
!
if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
bool ' USB verbose debug messages' CONFIG_USB_DEBUG
! comment 'Miscellaneous USB options'
bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
***************
*** 16,111 ****
define_bool CONFIG_USB_BANDWIDTH n
fi
bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
! comment 'USB Host Controller Drivers'
! source drivers/usb/hcd/Config.in
! if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
! dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
! fi
! if [ "$CONFIG_USB_UHCI" != "y" ]; then
! dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
! else
! define_bool CONFIG_USB_UHCI_ALT n
fi
! dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
! comment 'USB Device Class drivers'
! dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
! dep_tristate ' EMI 2|6 USB Audio interface support' CONFIG_USB_EMI26 $CONFIG_USB_AUDIO
! dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' USB MIDI support' CONFIG_USB_MIDI $CONFIG_USB
! if [ "$CONFIG_SCSI" = "n" ]; then
! comment ' SCSI support is needed for USB Storage'
! fi
! dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
! dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
! dep_mbool ' Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE
! dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
! dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
! dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' SanDisk SDDR-55 SmartMedia support' CONFIG_USB_STORAGE_SDDR55 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
! dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
!
! comment 'USB Human Interface Devices (HID)'
! dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB
! if [ "$CONFIG_INPUT" = "n" ]; then
! comment ' Input core support is needed for USB HID input layer or HIDBP support'
! fi
! dep_mbool ' HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID
! dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
if [ "$CONFIG_USB_HID" != "y" ]; then
dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
fi
- dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT
dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
! comment 'USB Imaging devices'
! dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
! dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
! dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
! dep_tristate ' HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
!
! comment 'USB Multimedia devices'
! if [ "$CONFIG_VIDEO_DEV" = "n" ]; then
! comment ' Video4Linux support is needed for USB Multimedia device support'
! else
! dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB STV680 (Pencam) Camera support' CONFIG_USB_STV680 $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
! dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
! dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
! fi
!
! comment 'USB Network adaptors'
! if [ "$CONFIG_NET" = "n" ]; then
! comment ' Networking support is needed for USB Networking device support'
! else
! dep_tristate ' USB Pegasus/Pegasus-II based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Realtek RTL8150 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_RTL8150 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! fi
! comment 'USB port drivers'
! dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
! source drivers/usb/serial/Config.in
!
! comment 'USB Miscellaneous drivers'
! dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' Texas Instruments Graph Link USB (aka SilverLink) cable support' CONFIG_USB_TIGL $CONFIG_USB
! dep_tristate ' Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' USB LCD device support' CONFIG_USB_LCD $CONFIG_USB
fi
endmenu
--- 24,115 ----
define_bool CONFIG_USB_BANDWIDTH n
fi
bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
+ fi
! comment 'USB Controllers'
! if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
! dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
! fi
! if [ "$CONFIG_USB_UHCI" != "y" ]; then
! dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
! else
! define_bool CONFIG_USB_UHCI_ALT n
! fi
! if [ "$CONFIG_8xx" = "y" ]; then
! dep_tristate ' MPC850/823 USB HCI support' CONFIG_USB_MPC8xx $CONFIG_USB
! if [ "$CONFIG_USB_MPC8xx" = "n" ]; then
! bool ' MPC850/823 USB Function (Client) support' CONFIG_USB_CLIENT_MPC8xx
fi
! fi
! dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
! if [ "$CONFIG_SA1111" = "y" ]; then
! dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB_OHCI
! fi
! dep_tristate ' Non-PCI OHCI support' CONFIG_USB_NON_PCI_OHCI $CONFIG_USB_OHCI
! comment 'USB Device Class drivers'
! dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
! dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
! dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
! dep_mbool ' Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE
! dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
! dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
! dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_mbool ' Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
! dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
!
! comment 'USB Human Interface Devices (HID)'
! if [ "$CONFIG_INPUT" = "n" ]; then
! comment ' Input core support is needed for USB HID'
! else
! dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
! dep_mbool ' /dev/hiddev raw HID device support (EXPERIMENTAL)' CONFIG_USB_HIDDEV $CONFIG_USB_HID
if [ "$CONFIG_USB_HID" != "y" ]; then
dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
fi
dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
+ fi
! comment 'USB Imaging devices'
! dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
! dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
! dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
! dep_tristate ' HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
!
! comment 'USB Multimedia devices'
! if [ "$CONFIG_VIDEO_DEV" = "n" ]; then
! comment ' Video4Linux support is needed for USB Multimedia device support'
! else
! dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
! dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
! dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
! fi
! comment 'USB Network adaptors'
! if [ "$CONFIG_NET" = "n" ]; then
! comment ' Networking support is needed for USB Networking device support'
! else
! dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
! dep_tristate ' USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
fi
+
+ comment 'USB port drivers'
+ dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
+ source drivers/usb/serial/Config.in
+
+ comment 'USB Miscellaneous drivers'
+ dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
+
endmenu
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/Makefile LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/Makefile
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/Makefile 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/Makefile 2004-05-24 17:35:29.000000000 +0900
***************
*** 10,22 ****
# Objects that export symbols.
! export-objs := hcd.o usb.o ov511.o pwc-uncompress.o
# Multipart objects.
! list-multi := usbcore.o hid.o pwc.o
usbcore-objs := usb.o usb-debug.o hub.o
! hid-objs := hid-core.o
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
--- 10,28 ----
# Objects that export symbols.
! export-objs := usb.o
# Multipart objects.
! list-multi := usbcore.o hid.o
usbcore-objs := usb.o usb-debug.o hub.o
! hid-objs := hid-core.o hid-input.o
!
! ifneq ($(CONFIG_USB_PWC),n)
! export-objs += pwc-uncompress.o
! list-multi += pwc.o
! endif
!
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
***************
*** 30,39 ****
hid-objs += hiddev.o
endif
- ifeq ($(CONFIG_USB_HIDINPUT),y)
- hid-objs += hid-input.o
- endif
-
# Object file lists.
obj-y :=
--- 36,41 ----
***************
*** 44,104 ****
# Each configuration option enables a list of files.
obj-$(CONFIG_USB) += usbcore.o
-
- # EHCI should initialize/link before the other HCDs
- ifeq ($(CONFIG_USB_EHCI_HCD),y)
- obj-y += hcd/ehci-hcd.o
- endif
-
obj-$(CONFIG_USB_UHCI) += usb-uhci.o
obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
obj-$(CONFIG_USB_OHCI) += usb-ohci.o
!
! ifneq ($(CONFIG_USB_EHCI_HCD),n)
! usbcore-objs += hcd.o
! endif
! subdir-$(CONFIG_USB_EHCI_HCD) += hcd
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_HID) += hid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
- obj-$(CONFIG_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_SCANNER) += scanner.o
obj-$(CONFIG_USB_ACM) += acm.o
obj-$(CONFIG_USB_PRINTER) += printer.o
obj-$(CONFIG_USB_AUDIO) += audio.o
- obj-$(CONFIG_USB_EMI26) += emi26.o
- obj-$(CONFIG_USB_MIDI) += usb-midi.o
obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
obj-$(CONFIG_USB_PWC) += pwc.o
obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_MDC800) += mdc800.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
- obj-$(CONFIG_USB_VICAM) += vicam.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
- obj-$(CONFIG_USB_STV680) += stv680.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
- obj-$(CONFIG_USB_RTL8150) += rtl8150.o
obj-$(CONFIG_USB_CATC) += catc.o
obj-$(CONFIG_USB_KAWETH) += kaweth.o
obj-$(CONFIG_USB_CDCETHER) += CDCEther.o
obj-$(CONFIG_USB_RIO500) += rio500.o
- obj-$(CONFIG_USB_TIGL) += tiglusb.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_MICROTEK) += microtek.o
obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o
obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
- obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
- obj-$(CONFIG_USB_BRLVGER) += brlvger.o
- obj-$(CONFIG_USB_LCD) += usblcd.o
# Object files in subdirectories
! mod-subdirs := serial hcd
subdir-$(CONFIG_USB_SERIAL) += serial
subdir-$(CONFIG_USB_STORAGE) += storage
--- 46,88 ----
# Each configuration option enables a list of files.
obj-$(CONFIG_USB) += usbcore.o
obj-$(CONFIG_USB_UHCI) += usb-uhci.o
obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
+ obj-$(CONFIG_USB_MPC8xx) += m8xxhci.o
obj-$(CONFIG_USB_OHCI) += usb-ohci.o
! obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci-sa1111.o
! obj-$(CONFIG_USB_NON_PCI_OHCI) += usb-ohci-nonpci.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_HID) += hid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_SCANNER) += scanner.o
obj-$(CONFIG_USB_ACM) += acm.o
obj-$(CONFIG_USB_PRINTER) += printer.o
obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
obj-$(CONFIG_USB_PWC) += pwc.o
obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_MDC800) += mdc800.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
obj-$(CONFIG_USB_CATC) += catc.o
obj-$(CONFIG_USB_KAWETH) += kaweth.o
obj-$(CONFIG_USB_CDCETHER) += CDCEther.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_MICROTEK) += microtek.o
obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o
obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
# Object files in subdirectories
! mod-subdirs := serial
subdir-$(CONFIG_USB_SERIAL) += serial
subdir-$(CONFIG_USB_STORAGE) += storage
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/acm.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/acm.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/acm.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/acm.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 184,190 ****
static void acm_ctrl_irq(struct urb *urb)
{
struct acm *acm = urb->context;
! struct usb_ctrlrequest *dr = urb->transfer_buffer;
unsigned char *data = (unsigned char *)(dr + 1);
int newctrl;
--- 184,190 ----
static void acm_ctrl_irq(struct urb *urb)
{
struct acm *acm = urb->context;
! devrequest *dr = urb->transfer_buffer;
unsigned char *data = (unsigned char *)(dr + 1);
int newctrl;
***************
*** 195,201 ****
return;
}
! switch (dr->bRequest) {
case ACM_IRQ_NETWORK:
--- 195,201 ----
return;
}
! switch (dr->request) {
case ACM_IRQ_NETWORK:
***************
*** 223,229 ****
default:
dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
! dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
return;
}
}
--- 223,229 ----
default:
dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
! dr->request, dr->index, dr->length, data[0], data[1]);
return;
}
}
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: aiptek.c
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/audio.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/audio.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/audio.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/audio.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 297,309 ****
#define FLG_CONNECTED 32
struct my_data_urb {
! struct urb urb;
! struct iso_packet_descriptor isoframe[DESCFRAMES];
};
struct my_sync_urb {
! struct urb urb;
! struct iso_packet_descriptor isoframe[SYNCFRAMES];
};
--- 297,309 ----
#define FLG_CONNECTED 32
struct my_data_urb {
! urb_t urb;
! iso_packet_descriptor_t isoframe[DESCFRAMES];
};
struct my_sync_urb {
! urb_t urb;
! iso_packet_descriptor_t isoframe[SYNCFRAMES];
};
***************
*** 399,405 ****
/* prevent picking up a bogus abs macro */
#undef abs
! static inline int abs(int x)
{
if (x < 0)
return -x;
--- 399,405 ----
/* prevent picking up a bogus abs macro */
#undef abs
! extern inline int abs(int x)
{
if (x < 0)
return -x;
***************
*** 408,414 ****
/* --------------------------------------------------------------------- */
! static inline unsigned ld2(unsigned int x)
{
unsigned r = 0;
--- 408,414 ----
/* --------------------------------------------------------------------- */
! extern inline unsigned ld2(unsigned int x)
{
unsigned r = 0;
***************
*** 833,839 ****
}
}
! static int usbin_prepare_desc(struct usbin *u, struct urb *urb)
{
unsigned int i, maxsize, offs;
--- 833,839 ----
}
}
! static int usbin_prepare_desc(struct usbin *u, purb_t urb)
{
unsigned int i, maxsize, offs;
***************
*** 850,856 ****
* return value: 0 if descriptor should be restarted, -1 otherwise
* convert sample format on the fly if necessary
*/
! static int usbin_retire_desc(struct usbin *u, struct urb *urb)
{
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;
unsigned char *cp;
--- 850,856 ----
* return value: 0 if descriptor should be restarted, -1 otherwise
* convert sample format on the fly if necessary
*/
! static int usbin_retire_desc(struct usbin *u, purb_t urb)
{
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;
unsigned char *cp;
***************
*** 930,936 ****
/*
* we output sync data
*/
! static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb)
{
unsigned char *cp = urb->transfer_buffer;
unsigned int i, offs;
--- 930,936 ----
/*
* we output sync data
*/
! static int usbin_sync_prepare_desc(struct usbin *u, purb_t urb)
{
unsigned char *cp = urb->transfer_buffer;
unsigned int i, offs;
***************
*** 948,954 ****
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
! static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb)
{
unsigned int i;
--- 948,954 ----
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
! static int usbin_sync_retire_desc(struct usbin *u, purb_t urb)
{
unsigned int i;
***************
*** 996,1002 ****
{
struct usb_device *dev = as->state->usbdev;
struct usbin *u = &as->usbin;
! struct urb *urb;
unsigned long flags;
unsigned int maxsze, bufsz;
--- 996,1002 ----
{
struct usb_device *dev = as->state->usbdev;
struct usbin *u = &as->usbin;
! purb_t urb;
unsigned long flags;
unsigned int maxsze, bufsz;
***************
*** 1186,1192 ****
}
}
! static int usbout_prepare_desc(struct usbout *u, struct urb *urb)
{
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;
unsigned char *cp = urb->transfer_buffer;
--- 1186,1192 ----
}
}
! static int usbout_prepare_desc(struct usbout *u, purb_t urb)
{
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;
unsigned char *cp = urb->transfer_buffer;
***************
*** 1238,1244 ****
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
! static int usbout_retire_desc(struct usbout *u, struct urb *urb)
{
unsigned int i;
--- 1238,1244 ----
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
! static int usbout_retire_desc(struct usbout *u, purb_t urb)
{
unsigned int i;
***************
*** 1285,1291 ****
spin_unlock_irqrestore(&as->lock, flags);
}
! static int usbout_sync_prepare_desc(struct usbout *u, struct urb *urb)
{
unsigned int i, offs;
--- 1285,1291 ----
spin_unlock_irqrestore(&as->lock, flags);
}
! static int usbout_sync_prepare_desc(struct usbout *u, purb_t urb)
{
unsigned int i, offs;
***************
*** 1299,1305 ****
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
! static int usbout_sync_retire_desc(struct usbout *u, struct urb *urb)
{
unsigned char *cp = urb->transfer_buffer;
unsigned int f, i;
--- 1299,1305 ----
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
! static int usbout_sync_retire_desc(struct usbout *u, purb_t urb)
{
unsigned char *cp = urb->transfer_buffer;
unsigned int f, i;
***************
*** 1361,1367 ****
{
struct usb_device *dev = as->state->usbdev;
struct usbout *u = &as->usbout;
! struct urb *urb;
unsigned long flags;
unsigned int maxsze, bufsz;
--- 1361,1367 ----
{
struct usb_device *dev = as->state->usbdev;
struct usbout *u = &as->usbout;
! purb_t urb;
unsigned long flags;
unsigned int maxsze, bufsz;
***************
*** 1931,1943 ****
kfree(s);
}
! static inline int prog_dmabuf_in(struct usb_audiodev *as)
{
usbin_stop(as);
return dmabuf_init(&as->usbin.dma);
}
! static inline int prog_dmabuf_out(struct usb_audiodev *as)
{
usbout_stop(as);
return dmabuf_init(&as->usbout.dma);
--- 1931,1943 ----
kfree(s);
}
! extern inline int prog_dmabuf_in(struct usb_audiodev *as)
{
usbin_stop(as);
return dmabuf_init(&as->usbin.dma);
}
! extern inline int prog_dmabuf_out(struct usb_audiodev *as)
{
usbout_stop(as);
return dmabuf_init(&as->usbout.dma);
***************
*** 2341,2346 ****
--- 2341,2347 ----
if (vma->vm_pgoff != 0)
goto out;
+ vma->vm_flags &= ~VM_IO;
ret = dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
out:
unlock_kernel();
***************
*** 2536,2542 ****
if (as->usbin.dma.mapped)
as->usbin.dma.count &= as->usbin.dma.fragsize-1;
spin_unlock_irqrestore(&as->lock, flags);
! return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_GETOPTR:
if (!(file->f_mode & FMODE_WRITE))
--- 2537,2543 ----
if (as->usbin.dma.mapped)
as->usbin.dma.count &= as->usbin.dma.fragsize-1;
spin_unlock_irqrestore(&as->lock, flags);
! return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
case SNDCTL_DSP_GETOPTR:
if (!(file->f_mode & FMODE_WRITE))
***************
*** 2548,2554 ****
if (as->usbout.dma.mapped)
as->usbout.dma.count &= as->usbout.dma.fragsize-1;
spin_unlock_irqrestore(&as->lock, flags);
! return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_GETBLKSIZE:
if (file->f_mode & FMODE_WRITE) {
--- 2549,2555 ----
if (as->usbout.dma.mapped)
as->usbout.dma.count &= as->usbout.dma.fragsize-1;
spin_unlock_irqrestore(&as->lock, flags);
! return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
case SNDCTL_DSP_GETBLKSIZE:
if (file->f_mode & FMODE_WRITE) {
***************
*** 3207,3213 ****
static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid);
! static inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
{
unsigned int idx;
--- 3208,3214 ----
static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid);
! extern inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
{
unsigned int idx;
***************
*** 3378,3387 ****
if (state->nrchannels > 2)
printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
! nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
! if (nr_logical_channels != state->nrchannels) {
! printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels);
if (state->nrchannels == 1 && nr_logical_channels==0) {
printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n");
--- 3379,3388 ----
if (state->nrchannels > 2)
printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
! nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
! if (nr_logical_channels != state->nrchannels) {
! printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels);
if (state->nrchannels == 1 && nr_logical_channels==0) {
printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n");
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: auerswald.c
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/bluetooth.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/bluetooth.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/bluetooth.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/bluetooth.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 4,15 ****
* Copyright (c) 2000, 2001 Greg Kroah-Hartman
* Copyright (c) 2000 Mark Douglas Corner
*
! * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
*
- * (2001/11/30) Version 0.13 gkh
- * - added locking patch from Masoodur Rahman
- * - removed active variable, as open_count will do.
- *
* (2001/07/09) Version 0.12 gkh
* - removed in_interrupt() call, as it doesn't make sense to do
* that anymore.
--- 4,11 ----
* Copyright (c) 2000, 2001 Greg Kroah-Hartman
* Copyright (c) 2000 Mark Douglas Corner
*
! * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
*
* (2001/07/09) Version 0.12 gkh
* - removed in_interrupt() call, as it doesn't make sense to do
* that anymore.
***************
*** 104,117 ****
#include
#include
#include
#include
#include
#include
#include
#include
- #include
#define DEBUG
#include
--- 100,116 ----
#include
+ #include
+ #include
#include
+ #include
#include
#include
+ #include
#include
#include
#include
#include
#define DEBUG
#include
***************
*** 119,125 ****
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.13"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
#define DRIVER_DESC "USB Bluetooth tty driver"
--- 118,124 ----
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.12"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
#define DRIVER_DESC "USB Bluetooth tty driver"
***************
*** 171,182 ****
struct tty_struct * tty; /* the coresponding tty for this port */
unsigned char minor; /* the starting minor number for this device */
int throttle; /* throttled by tty layer */
- int open_count;
__u8 control_out_bInterfaceNum;
struct urb * control_urb_pool[NUM_CONTROL_URBS];
! struct usb_ctrlrequest dr[NUM_CONTROL_URBS];
unsigned char * interrupt_in_buffer;
struct urb * interrupt_in_urb;
--- 170,181 ----
struct tty_struct * tty; /* the coresponding tty for this port */
unsigned char minor; /* the starting minor number for this device */
+ char active; /* someone has this device open */
int throttle; /* throttled by tty layer */
__u8 control_out_bInterfaceNum;
struct urb * control_urb_pool[NUM_CONTROL_URBS];
! devrequest dr[NUM_CONTROL_URBS];
unsigned char * interrupt_in_buffer;
struct urb * interrupt_in_urb;
***************
*** 201,207 ****
unsigned char int_buffer[EVENT_BUFFER_SIZE];
unsigned int bulk_packet_pos;
unsigned char bulk_buffer[ACL_BUFFER_SIZE]; /* 64k preallocated, fix? */
- struct semaphore lock;
};
--- 200,205 ----
***************
*** 234,243 ****
MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
static struct usb_driver usb_bluetooth_driver = {
! .name = "bluetty",
! .probe = usb_bluetooth_probe,
! .disconnect = usb_bluetooth_disconnect,
! .id_table = usb_bluetooth_ids,
};
static int bluetooth_refcount;
--- 232,241 ----
MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
static struct usb_driver usb_bluetooth_driver = {
! name: "bluetooth",
! probe: usb_bluetooth_probe,
! disconnect: usb_bluetooth_disconnect,
! id_table: usb_bluetooth_ids,
};
static int bluetooth_refcount;
***************
*** 285,295 ****
static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
{
struct urb *urb = NULL;
! struct usb_ctrlrequest *dr = NULL;
int i;
int status;
! dbg ("%s", __FUNCTION__);
/* try to find a free urb in our list */
for (i = 0; i < NUM_CONTROL_URBS; ++i) {
--- 283,293 ----
static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
{
struct urb *urb = NULL;
! devrequest *dr = NULL;
int i;
int status;
! dbg (__FUNCTION__);
/* try to find a free urb in our list */
for (i = 0; i < NUM_CONTROL_URBS; ++i) {
***************
*** 300,306 ****
}
}
if (urb == NULL) {
! dbg ("%s - no free urbs", __FUNCTION__);
return -ENOMEM;
}
--- 298,304 ----
}
}
if (urb == NULL) {
! dbg (__FUNCTION__ " - no free urbs");
return -ENOMEM;
}
***************
*** 308,314 ****
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
! err ("%s - out of memory", __FUNCTION__);
return -ENOMEM;
}
}
--- 306,312 ----
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
! err (__FUNCTION__" - out of memory");
return -ENOMEM;
}
}
***************
*** 316,332 ****
kfree (urb->transfer_buffer);
urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
! err ("%s - out of memory", __FUNCTION__);
return -ENOMEM;
}
}
memcpy (urb->transfer_buffer, buf, len);
! dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE;
! dr->bRequest = request;
! dr->wValue = cpu_to_le16((u16) value);
! dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
! dr->wLength = cpu_to_le16((u16) len);
FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
(unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
--- 314,330 ----
kfree (urb->transfer_buffer);
urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
! err (__FUNCTION__" - out of memory");
return -ENOMEM;
}
}
memcpy (urb->transfer_buffer, buf, len);
! dr->requesttype = BLUETOOTH_CONTROL_REQUEST_TYPE;
! dr->request = request;
! dr->value = cpu_to_le16((u16) value);
! dr->index = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
! dr->length = cpu_to_le16((u16) len);
FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
(unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
***************
*** 334,340 ****
/* send it down the pipe */
status = usb_submit_urb(urb);
if (status)
! dbg("%s - usb_submit_urb(control) failed with status = %d", __FUNCTION__, status);
return status;
}
--- 332,338 ----
/* send it down the pipe */
status = usb_submit_urb(urb);
if (status)
! dbg(__FUNCTION__ " - usb_submit_urb(control) failed with status = %d", status);
return status;
}
***************
*** 351,357 ****
struct usb_bluetooth *bluetooth;
int result;
! dbg("%s", __FUNCTION__);
/* initialize the pointer incase something fails */
tty->driver_data = NULL;
--- 349,355 ----
struct usb_bluetooth *bluetooth;
int result;
! dbg(__FUNCTION__);
/* initialize the pointer incase something fails */
tty->driver_data = NULL;
***************
*** 363,408 ****
return -ENODEV;
}
! down (&bluetooth->lock);
!
! ++bluetooth->open_count;
! if (bluetooth->open_count == 1) {
! /* set up our structure making the tty driver remember our object, and us it */
! tty->driver_data = bluetooth;
! bluetooth->tty = tty;
!
! /* force low_latency on so that our tty_push actually forces the data through,
! * otherwise it is scheduled, and with high data rates (like with OHCI) data
! * can get lost. */
! bluetooth->tty->low_latency = 1;
! /* Reset the packet position counters */
! bluetooth->int_packet_pos = 0;
! bluetooth->bulk_packet_pos = 0;
#ifndef BTBUGGYHARDWARE
! /* Start reading from the device */
! FILL_BULK_URB (bluetooth->read_urb, bluetooth->dev,
! usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
! bluetooth->bulk_in_buffer,
! bluetooth->bulk_in_buffer_size,
! bluetooth_read_bulk_callback, bluetooth);
! result = usb_submit_urb(bluetooth->read_urb);
! if (result)
! dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
#endif
! FILL_INT_URB (bluetooth->interrupt_in_urb, bluetooth->dev,
! usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
! bluetooth->interrupt_in_buffer,
! bluetooth->interrupt_in_buffer_size,
! bluetooth_int_callback, bluetooth,
! bluetooth->interrupt_in_interval);
! result = usb_submit_urb(bluetooth->interrupt_in_urb);
! if (result)
! dbg("%s - usb_submit_urb(interrupt in) failed with status %d", __FUNCTION__, result);
! }
!
! up(&bluetooth->lock);
return 0;
}
--- 361,403 ----
return -ENODEV;
}
! if (bluetooth->active) {
! dbg (__FUNCTION__ " - device already open");
! return -EINVAL;
! }
!
! /* set up our structure making the tty driver remember our object, and us it */
! tty->driver_data = bluetooth;
! bluetooth->tty = tty;
!
! /* force low_latency on so that our tty_push actually forces the data through,
! * otherwise it is scheduled, and with high data rates (like with OHCI) data
! * can get lost. */
! bluetooth->tty->low_latency = 1;
! bluetooth->active = 1;
!
! /* Reset the packet position counters */
! bluetooth->int_packet_pos = 0;
! bluetooth->bulk_packet_pos = 0;
#ifndef BTBUGGYHARDWARE
! /* Start reading from the device */
! FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev,
! usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
! bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size,
! bluetooth_read_bulk_callback, bluetooth);
! result = usb_submit_urb(bluetooth->read_urb);
! if (result)
! dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
#endif
! FILL_INT_URB(bluetooth->interrupt_in_urb, bluetooth->dev,
! usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
! bluetooth->interrupt_in_buffer, bluetooth->interrupt_in_buffer_size,
! bluetooth_int_callback, bluetooth, bluetooth->interrupt_in_interval);
! result = usb_submit_urb(bluetooth->interrupt_in_urb);
! if (result)
! dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
return 0;
}
***************
*** 417,442 ****
return;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not opened", __FUNCTION__);
return;
}
! down (&bluetooth->lock);
!
! --bluetooth->open_count;
! if (bluetooth->open_count <= 0) {
! bluetooth->open_count = 0;
! /* shutdown any bulk reads and writes that might be going on */
! for (i = 0; i < NUM_BULK_URBS; ++i)
! usb_unlink_urb (bluetooth->write_urb_pool[i]);
! usb_unlink_urb (bluetooth->read_urb);
! usb_unlink_urb (bluetooth->interrupt_in_urb);
! }
! up(&bluetooth->lock);
}
--- 412,431 ----
return;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not opened");
return;
}
! /* shutdown any bulk reads and writes that might be going on */
! for (i = 0; i < NUM_BULK_URBS; ++i)
! usb_unlink_urb (bluetooth->write_urb_pool[i]);
! usb_unlink_urb (bluetooth->read_urb);
! usb_unlink_urb (bluetooth->interrupt_in_urb);
! bluetooth->active = 0;
}
***************
*** 456,479 ****
return -ENODEV;
}
! dbg("%s - %d byte(s)", __FUNCTION__, count);
! if (!bluetooth->open_count) {
! dbg ("%s - device not opened", __FUNCTION__);
return -EINVAL;
}
if (count == 0) {
! dbg("%s - write request of 0 bytes", __FUNCTION__);
return 0;
}
if (count == 1) {
! dbg("%s - write request only included type %d", __FUNCTION__, buf[0]);
return 1;
}
#ifdef DEBUG
! printk (KERN_DEBUG __FILE__ ": %s - length = %d, data = ", __FUNCTION__, count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", buf[i]);
}
--- 445,468 ----
return -ENODEV;
}
! dbg(__FUNCTION__ " - %d byte(s)", count);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not opened");
return -EINVAL;
}
if (count == 0) {
! dbg(__FUNCTION__ " - write request of 0 bytes");
return 0;
}
if (count == 1) {
! dbg(__FUNCTION__ " - write request only included type %d", buf[0]);
return 1;
}
#ifdef DEBUG
! printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", buf[i]);
}
***************
*** 483,496 ****
if (from_user) {
temp_buffer = kmalloc (count, GFP_KERNEL);
if (temp_buffer == NULL) {
! err ("%s - out of memory.", __FUNCTION__);
retval = -ENOMEM;
goto exit;
}
! if (copy_from_user (temp_buffer, buf, count)) {
! retval = -EFAULT;
! goto exit;
! }
current_buffer = temp_buffer;
} else {
current_buffer = buf;
--- 472,482 ----
if (from_user) {
temp_buffer = kmalloc (count, GFP_KERNEL);
if (temp_buffer == NULL) {
! err (__FUNCTION__ "- out of memory.");
retval = -ENOMEM;
goto exit;
}
! copy_from_user (temp_buffer, buf, count);
current_buffer = temp_buffer;
} else {
current_buffer = buf;
***************
*** 499,505 ****
switch (*current_buffer) {
/* First byte indicates the type of packet */
case CMD_PKT:
! /* dbg("%s- Send cmd_pkt len:%d", __FUNCTION__, count);*/
retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, ¤t_buffer[1], count-1);
if (retval) {
--- 485,491 ----
switch (*current_buffer) {
/* First byte indicates the type of packet */
case CMD_PKT:
! /* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/
retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, ¤t_buffer[1], count-1);
if (retval) {
***************
*** 525,531 ****
}
}
if (urb == NULL) {
! dbg ("%s - no free urbs", __FUNCTION__);
retval = bytes_sent;
goto exit;
}
--- 511,517 ----
}
}
if (urb == NULL) {
! dbg (__FUNCTION__ " - no free urbs");
retval = bytes_sent;
goto exit;
}
***************
*** 542,548 ****
/* send it down the pipe */
retval = usb_submit_urb(urb);
if (retval) {
! dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval);
goto exit;
}
#ifdef BTBUGGYHARDWARE
--- 528,534 ----
/* send it down the pipe */
retval = usb_submit_urb(urb);
if (retval) {
! dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with error = %d", retval);
goto exit;
}
#ifdef BTBUGGYHARDWARE
***************
*** 561,567 ****
break;
default :
! dbg("%s - unsupported (at this time) write type", __FUNCTION__);
retval = -EINVAL;
break;
}
--- 547,553 ----
break;
default :
! dbg(__FUNCTION__" - unsupported (at this time) write type");
retval = -EINVAL;
break;
}
***************
*** 584,593 ****
return -ENODEV;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return -EINVAL;
}
--- 570,579 ----
return -ENODEV;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return -EINVAL;
}
***************
*** 597,603 ****
}
}
! dbg("%s - returns %d", __FUNCTION__, room);
return room;
}
--- 583,589 ----
}
}
! dbg(__FUNCTION__ " - returns %d", room);
return room;
}
***************
*** 612,619 ****
return -ENODEV;
}
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return -EINVAL;
}
--- 598,605 ----
return -ENODEV;
}
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return -EINVAL;
}
***************
*** 623,629 ****
}
}
! dbg ("%s - returns %d", __FUNCTION__, chars);
return chars;
}
--- 609,615 ----
}
}
! dbg (__FUNCTION__ " - returns %d", chars);
return chars;
}
***************
*** 636,649 ****
return;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return;
}
! dbg("%s unsupported (at this time)", __FUNCTION__);
return;
}
--- 622,635 ----
return;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return;
}
! dbg(__FUNCTION__ " unsupported (at this time)");
return;
}
***************
*** 657,670 ****
return;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return;
}
! dbg("%s unsupported (at this time)", __FUNCTION__);
}
--- 643,656 ----
return;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return;
}
! dbg(__FUNCTION__ " unsupported (at this time)");
}
***************
*** 676,685 ****
return -ENODEV;
}
! dbg("%s - cmd 0x%.4x", __FUNCTION__, cmd);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return -ENODEV;
}
--- 662,671 ----
return -ENODEV;
}
! dbg(__FUNCTION__ " - cmd 0x%.4x", cmd);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return -ENODEV;
}
***************
*** 696,705 ****
return;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return;
}
--- 682,691 ----
return;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return;
}
***************
*** 718,727 ****
return;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return;
}
--- 704,713 ----
return;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return;
}
***************
*** 732,738 ****
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb);
if (result)
! err ("%s - failed submitting read urb, error %d", __FUNCTION__, result);
}
}
--- 718,724 ----
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb);
if (result)
! err (__FUNCTION__ " - failed submitting read urb, error %d", result);
}
}
***************
*** 743,752 ****
return;
}
! dbg("%s", __FUNCTION__);
! if (!bluetooth->open_count) {
! dbg ("%s - device not open", __FUNCTION__);
return;
}
--- 729,738 ----
return;
}
! dbg(__FUNCTION__);
! if (!bluetooth->active) {
! dbg (__FUNCTION__ " - device not open");
return;
}
***************
*** 769,795 ****
unsigned int count = urb->actual_length;
unsigned int packet_size;
! dbg("%s", __FUNCTION__);
if (!bluetooth) {
! dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
! dbg("%s - nonzero int status received: %d", __FUNCTION__, urb->status);
return;
}
if (!count) {
! dbg("%s - zero length int", __FUNCTION__);
return;
}
#ifdef DEBUG
if (count) {
! printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", data[i]);
}
--- 755,781 ----
unsigned int count = urb->actual_length;
unsigned int packet_size;
! dbg(__FUNCTION__);
if (!bluetooth) {
! dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
! dbg(__FUNCTION__ " - nonzero int status received: %d", urb->status);
return;
}
if (!count) {
! dbg(__FUNCTION__ " - zero length int");
return;
}
#ifdef DEBUG
if (count) {
! printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", data[i]);
}
***************
*** 819,825 ****
}
if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
! err("%s - exceeded EVENT_BUFFER_SIZE", __FUNCTION__);
bluetooth->int_packet_pos = 0;
return;
}
--- 805,811 ----
}
if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
! err(__FUNCTION__ " - exceeded EVENT_BUFFER_SIZE");
bluetooth->int_packet_pos = 0;
return;
}
***************
*** 835,841 ****
return;
if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
! err("%s - packet was too long", __FUNCTION__);
bluetooth->int_packet_pos = 0;
return;
}
--- 821,827 ----
return;
if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
! err(__FUNCTION__ " - packet was too long");
bluetooth->int_packet_pos = 0;
return;
}
***************
*** 859,873 ****
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
! dbg("%s", __FUNCTION__);
if (!bluetooth) {
! dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
! dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
return;
}
}
--- 845,859 ----
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
! dbg(__FUNCTION__);
if (!bluetooth) {
! dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
! dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
return;
}
}
***************
*** 883,912 ****
int result;
! dbg("%s", __FUNCTION__);
if (!bluetooth) {
! dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
! dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
if (urb->status == -ENOENT) {
! dbg("%s - URB canceled, won't reschedule", __FUNCTION__);
return;
}
goto exit;
}
if (!count) {
! dbg("%s - zero length read bulk", __FUNCTION__);
goto exit;
}
#ifdef DEBUG
if (count) {
! printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", data[i]);
}
--- 869,898 ----
int result;
! dbg(__FUNCTION__);
if (!bluetooth) {
! dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
! dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
if (urb->status == -ENOENT) {
! dbg(__FUNCTION__ " - URB canceled, won't reschedule");
return;
}
goto exit;
}
if (!count) {
! dbg(__FUNCTION__ " - zero length read bulk");
goto exit;
}
#ifdef DEBUG
if (count) {
! printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", data[i]);
}
***************
*** 923,929 ****
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb);
if (result)
! err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
return;
}
--- 909,915 ----
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb);
if (result)
! err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
}
***************
*** 940,946 ****
}
if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
! err("%s - exceeded ACL_BUFFER_SIZE", __FUNCTION__);
bluetooth->bulk_packet_pos = 0;
goto exit;
}
--- 926,932 ----
}
if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
! err(__FUNCTION__ " - exceeded ACL_BUFFER_SIZE");
bluetooth->bulk_packet_pos = 0;
goto exit;
}
***************
*** 957,963 ****
}
if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
! err("%s - packet was too long", __FUNCTION__);
bluetooth->bulk_packet_pos = 0;
goto exit;
}
--- 943,949 ----
}
if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
! err(__FUNCTION__ " - packet was too long");
bluetooth->bulk_packet_pos = 0;
goto exit;
}
***************
*** 975,981 ****
}
exit:
! if (!bluetooth || !bluetooth->open_count)
return;
FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev,
--- 961,967 ----
}
exit:
! if (!bluetooth || !bluetooth->active)
return;
FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev,
***************
*** 984,990 ****
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb);
if (result)
! err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
return;
}
--- 970,976 ----
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb);
if (result)
! err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
}
***************
*** 994,1008 ****
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
! dbg("%s", __FUNCTION__);
if (!bluetooth) {
! dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
! dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
return;
}
--- 980,994 ----
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
! dbg(__FUNCTION__);
if (!bluetooth) {
! dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
! dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
return;
}
***************
*** 1018,1024 ****
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
struct tty_struct *tty;
! dbg("%s", __FUNCTION__);
if (!bluetooth) {
return;
--- 1004,1010 ----
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
struct tty_struct *tty;
! dbg(__FUNCTION__);
if (!bluetooth) {
return;
***************
*** 1026,1032 ****
tty = bluetooth->tty;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
! dbg("%s - write wakeup call.", __FUNCTION__);
(tty->ldisc.write_wakeup)(tty);
}
--- 1012,1018 ----
tty = bluetooth->tty;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
! dbg(__FUNCTION__ " - write wakeup call.");
(tty->ldisc.write_wakeup)(tty);
}
***************
*** 1088,1094 ****
if ((num_bulk_in != 1) ||
(num_bulk_out != 1) ||
(num_interrupt_in != 1)) {
! dbg ("%s - improper number of endpoints. Bluetooth driver not bound.", __FUNCTION__);
return NULL;
}
--- 1074,1080 ----
if ((num_bulk_in != 1) ||
(num_bulk_out != 1) ||
(num_interrupt_in != 1)) {
! dbg (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound.");
return NULL;
}
***************
*** 1116,1122 ****
bluetooth->minor = minor;
bluetooth->tqueue.routine = bluetooth_softint;
bluetooth->tqueue.data = bluetooth;
- init_MUTEX(&bluetooth->lock);
/* record the interface number for the control out */
bluetooth->control_out_bInterfaceNum = control_out_endpoint;
--- 1102,1107 ----
***************
*** 1151,1158 ****
endpoint = bulk_out_endpoint[0];
bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
! bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
!
/* create our write urb pool */
for (i = 0; i < NUM_BULK_URBS; ++i) {
struct urb *urb = usb_alloc_urb(0);
--- 1136,1142 ----
endpoint = bulk_out_endpoint[0];
bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
!
/* create our write urb pool */
for (i = 0; i < NUM_BULK_URBS; ++i) {
struct urb *urb = usb_alloc_urb(0);
***************
*** 1167,1172 ****
--- 1151,1158 ----
}
bluetooth->write_urb_pool[i] = urb;
}
+
+ bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
endpoint = interrupt_in_endpoint[0];
bluetooth->interrupt_in_urb = usb_alloc_urb(0);
***************
*** 1231,1240 ****
int i;
if (bluetooth) {
! if ((bluetooth->open_count) && (bluetooth->tty))
tty_hangup(bluetooth->tty);
! bluetooth->open_count = 0;
if (bluetooth->read_urb) {
usb_unlink_urb (bluetooth->read_urb);
--- 1217,1226 ----
int i;
if (bluetooth) {
! if ((bluetooth->active) && (bluetooth->tty))
tty_hangup(bluetooth->tty);
! bluetooth->active = 0;
if (bluetooth->read_urb) {
usb_unlink_urb (bluetooth->read_urb);
***************
*** 1285,1314 ****
static struct tty_driver bluetooth_tty_driver = {
! .magic = TTY_DRIVER_MAGIC,
! .driver_name = "usb-bluetooth",
! .name = "usb/ttub/%d",
! .major = BLUETOOTH_TTY_MAJOR,
! .minor_start = 0,
! .num = BLUETOOTH_TTY_MINORS,
! .type = TTY_DRIVER_TYPE_SERIAL,
! .subtype = SERIAL_TYPE_NORMAL,
! .flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
!
! .refcount = &bluetooth_refcount,
! .table = bluetooth_tty,
! .termios = bluetooth_termios,
! .termios_locked = bluetooth_termios_locked,
!
! .open = bluetooth_open,
! .close = bluetooth_close,
! .write = bluetooth_write,
! .write_room = bluetooth_write_room,
! .ioctl = bluetooth_ioctl,
! .set_termios = bluetooth_set_termios,
! .throttle = bluetooth_throttle,
! .unthrottle = bluetooth_unthrottle,
! .chars_in_buffer = bluetooth_chars_in_buffer,
};
--- 1271,1300 ----
static struct tty_driver bluetooth_tty_driver = {
! magic: TTY_DRIVER_MAGIC,
! driver_name: "usb-bluetooth",
! name: "usb/ttub/%d",
! major: BLUETOOTH_TTY_MAJOR,
! minor_start: 0,
! num: BLUETOOTH_TTY_MINORS,
! type: TTY_DRIVER_TYPE_SERIAL,
! subtype: SERIAL_TYPE_NORMAL,
! flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
!
! refcount: &bluetooth_refcount,
! table: bluetooth_tty,
! termios: bluetooth_termios,
! termios_locked: bluetooth_termios_locked,
!
! open: bluetooth_open,
! close: bluetooth_close,
! write: bluetooth_write,
! write_room: bluetooth_write_room,
! ioctl: bluetooth_ioctl,
! set_termios: bluetooth_set_termios,
! throttle: bluetooth_throttle,
! unthrottle: bluetooth_unthrottle,
! chars_in_buffer: bluetooth_chars_in_buffer,
};
***************
*** 1328,1334 ****
bluetooth_tty_driver.init_termios = tty_std_termios;
bluetooth_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&bluetooth_tty_driver)) {
! err("%s - failed to register tty driver", __FUNCTION__);
return -1;
}
--- 1314,1320 ----
bluetooth_tty_driver.init_termios = tty_std_termios;
bluetooth_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&bluetooth_tty_driver)) {
! err(__FUNCTION__ " - failed to register tty driver");
return -1;
}
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: brlvger.c
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/catc.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/catc.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/catc.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/catc.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 7,15 ****
*
* Based on the work of
* Donald Becker
- *
- * Old chipset support added by Simon Evans 2002
- * - adds support for Belkin F5U011
*/
/*
--- 7,12 ----
***************
*** 41,49 ****
#include
#include
#include
- #include
#include
- #include
#undef DEBUG
--- 38,44 ----
***************
*** 53,62 ****
* Version information.
*/
! #define DRIVER_VERSION "v2.8"
#define DRIVER_AUTHOR "Vojtech Pavlik "
#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
- #define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
--- 48,56 ----
* Version information.
*/
! #define DRIVER_VERSION "v2.7"
#define DRIVER_AUTHOR "Vojtech Pavlik "
#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
***************
*** 72,78 ****
#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */
#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */
#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */
- #define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */
/*
* Control requests.
--- 66,71 ----
***************
*** 83,89 ****
GetMac = 0xf2,
Reset = 0xf4,
SetMac = 0xf5,
- SetRxMode = 0xf5, /* F5U011 only */
WriteROM = 0xf8,
SetReg = 0xfa,
GetReg = 0xfb,
--- 76,81 ----
***************
*** 131,137 ****
RxForceOK = 0x04,
RxMultiCast = 0x08,
RxPromisc = 0x10,
- AltRxPromisc = 0x20, /* F5U011 uses different bit */
};
enum led_values {
--- 123,128 ----
***************
*** 142,153 ****
LEDLink = 0x08,
};
- enum link_status {
- LinkNoChange = 0,
- LinkGood = 1,
- LinkBad = 2
- };
-
/*
* The catc struct.
*/
--- 133,138 ----
***************
*** 171,177 ****
u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)];
u8 irq_buf[2];
u8 ctrl_buf[64];
! struct usb_ctrlrequest ctrl_dr;
struct timer_list timer;
u8 stats_buf[8];
--- 156,162 ----
u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)];
u8 irq_buf[2];
u8 ctrl_buf[64];
! devrequest ctrl_dr;
struct timer_list timer;
u8 stats_buf[8];
***************
*** 191,200 ****
} ctrl_queue[CTRL_QUEUE];
struct urb tx_urb, rx_urb, irq_urb, ctrl_urb;
-
- u8 is_f5u011; /* Set if device is an F5U011 */
- u8 rxmode[2]; /* Used for F5U011 */
- atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
};
/*
--- 176,181 ----
***************
*** 208,217 ****
#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size)
- #define f5u011_rxmode(catc, rxmode) catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
- #define f5u011_rxmode_async(catc, rxmode) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
- #define f5u011_mchash_async(catc, hash) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
-
#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
--- 189,194 ----
***************
*** 225,236 ****
struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb;
! int pkt_len, pkt_offset = 0;
! if (!catc->is_f5u011) {
! clear_bit(RX_RUNNING, &catc->flags);
! pkt_offset = 2;
! }
if (urb->status) {
dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
--- 202,210 ----
struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb;
! int pkt_len;
! clear_bit(RX_RUNNING, &catc->flags);
if (urb->status) {
dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
***************
*** 238,259 ****
}
do {
! if(!catc->is_f5u011) {
! pkt_len = le16_to_cpup((u16*)pkt_start);
! if (pkt_len > urb->actual_length) {
! catc->stats.rx_length_errors++;
! catc->stats.rx_errors++;
! break;
! }
! } else {
! pkt_len = urb->actual_length;
}
if (!(skb = dev_alloc_skb(pkt_len)))
return;
skb->dev = catc->netdev;
! eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev);
--- 212,230 ----
}
do {
! pkt_len = le16_to_cpup((u16*)pkt_start);
!
! if (pkt_len > urb->actual_length) {
! catc->stats.rx_length_errors++;
! catc->stats.rx_errors++;
! break;
}
if (!(skb = dev_alloc_skb(pkt_len)))
return;
skb->dev = catc->netdev;
! eth_copy_and_sum(skb, pkt_start + 2, pkt_len, 0);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev);
***************
*** 262,289 ****
catc->stats.rx_packets++;
catc->stats.rx_bytes += pkt_len;
- /* F5U011 only does one packet per RX */
- if (catc->is_f5u011)
- break;
pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
catc->netdev->last_rx = jiffies;
-
- if (catc->is_f5u011) {
- if (atomic_read(&catc->recq_sz)) {
- int status;
- atomic_dec(&catc->recq_sz);
- dbg("getting extra packet");
- urb->dev = catc->usbdev;
- if ((status = usb_submit_urb(urb)) < 0) {
- dbg("submit(rx_urb) status %d", status);
- }
- } else {
- clear_bit(RX_RUNNING, &catc->flags);
- }
- }
}
static void catc_irq_done(struct urb *urb)
--- 233,243 ----
***************
*** 291,338 ****
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
int status;
- unsigned int hasdata = 0, linksts = LinkNoChange;
-
- if (!catc->is_f5u011) {
- hasdata = data[1] & 0x80;
- if (data[1] & 0x40)
- linksts = LinkGood;
- else if (data[1] & 0x20)
- linksts = LinkBad;
- } else {
- hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
- if (data[0] == 0x90)
- linksts = LinkGood;
- else if (data[0] == 0xA0)
- linksts = LinkBad;
- }
if (urb->status) {
dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
return;
}
! if (linksts == LinkGood) {
! netif_carrier_on(catc->netdev);
! dbg("link ok");
}
! if (linksts == LinkBad) {
! netif_carrier_off(catc->netdev);
! dbg("link bad");
! }
! if (hasdata) {
! if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
! if (catc->is_f5u011)
! atomic_inc(&catc->recq_sz);
! } else {
! catc->rx_urb.dev = catc->usbdev;
! if ((status = usb_submit_urb(&catc->rx_urb)) < 0) {
! err("submit(rx_urb) status %d", status);
! }
! }
! }
}
/*
--- 245,269 ----
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
int status;
if (urb->status) {
dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
return;
}
! if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) {
! catc->rx_urb.dev = catc->usbdev;
! if ((status = usb_submit_urb(&catc->rx_urb)) < 0) {
! err("submit(rx_urb) status %d", status);
! return;
! }
}
! if (data[1] & 0x40)
! dbg("link ok");
! if (data[1] & 0x20)
! dbg("link bad");
}
/*
***************
*** 343,351 ****
{
int status;
- if (catc->is_f5u011)
- catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
-
catc->tx_urb.transfer_buffer_length = catc->tx_ptr;
catc->tx_urb.transfer_buffer = catc->tx_buf[catc->tx_idx];
catc->tx_urb.dev = catc->usbdev;
--- 274,279 ----
***************
*** 402,417 ****
catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
! *((u16*)tx_buf) = (catc->is_f5u011) ?
! cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
memcpy(tx_buf + 2, skb->data, skb->len);
catc->tx_ptr += skb->len + 2;
if (!test_and_set_bit(TX_RUNNING, &catc->flags))
catc_tx_run(catc);
! if ((catc->is_f5u011 && catc->tx_ptr)
! || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
netif_stop_queue(netdev);
spin_unlock_irqrestore(&catc->tx_lock, flags);
--- 330,343 ----
catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
! *((u16*)tx_buf) = cpu_to_le16((u16)skb->len);
memcpy(tx_buf + 2, skb->data, skb->len);
catc->tx_ptr += skb->len + 2;
if (!test_and_set_bit(TX_RUNNING, &catc->flags))
catc_tx_run(catc);
! if (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))
netif_stop_queue(netdev);
spin_unlock_irqrestore(&catc->tx_lock, flags);
***************
*** 450,463 ****
struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
struct usb_device *usbdev = catc->usbdev;
struct urb *urb = &catc->ctrl_urb;
! struct usb_ctrlrequest *dr = &catc->ctrl_dr;
int status;
! dr->bRequest = q->request;
! dr->bRequestType = 0x40 | q->dir;
! dr->wValue = cpu_to_le16(q->value);
! dr->wIndex = cpu_to_le16(q->index);
! dr->wLength = cpu_to_le16(q->len);
urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);
urb->transfer_buffer_length = q->len;
--- 376,389 ----
struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
struct usb_device *usbdev = catc->usbdev;
struct urb *urb = &catc->ctrl_urb;
! devrequest *dr = &catc->ctrl_dr;
int status;
! dr->request = q->request;
! dr->requesttype = 0x40 | q->dir;
! dr->value = cpu_to_le16(q->value);
! dr->index = cpu_to_le16(q->index);
! dr->length = cpu_to_le16(q->len);
urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);
urb->transfer_buffer_length = q->len;
***************
*** 476,482 ****
{
struct catc *catc = urb->context;
struct ctrl_queue *q;
! unsigned long flags;
if (urb->status)
dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
--- 402,408 ----
{
struct catc *catc = urb->context;
struct ctrl_queue *q;
! long flags;
if (urb->status)
dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
***************
*** 510,516 ****
{
struct ctrl_queue *q;
int retval = 0;
! unsigned long flags;
spin_lock_irqsave(&catc->ctrl_lock, flags);
--- 436,442 ----
{
struct ctrl_queue *q;
int retval = 0;
! long flags;
spin_lock_irqsave(&catc->ctrl_lock, flags);
***************
*** 596,615 ****
* Receive modes. Broadcast, Multicast, Promisc.
*/
! static inline u32 ether_crc_le(int cnt, unsigned char *addr)
{
unsigned int crc = 0xffffffff;
u8 byte, idx, bit;
!
! for (idx = 0; idx < cnt; idx++)
for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1)
crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0);
- return crc;
- }
- static void catc_multicast(unsigned char *addr, u8 *multicast)
- {
- unsigned int crc = ether_crc_le(6, addr);
multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
}
--- 522,536 ----
* Receive modes. Broadcast, Multicast, Promisc.
*/
! static void catc_multicast(unsigned char *addr, u8 *multicast)
{
unsigned int crc = 0xffffffff;
u8 byte, idx, bit;
!
! for (idx = 0; idx < 6; idx++)
for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1)
crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0);
multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
}
***************
*** 629,735 ****
if (netdev->flags & IFF_PROMISC) {
memset(catc->multicast, 0xff, 64);
! rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
}
! if (netdev->flags & IFF_ALLMULTI) {
memset(catc->multicast, 0xff, 64);
- } else {
- for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
- u32 crc = ether_crc_le(6, mc->dmi_addr);
- if (!catc->is_f5u011) {
- catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
- } else {
- catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
- }
- }
- }
- if (!catc->is_f5u011) {
- catc_set_reg_async(catc, RxUnit, rx);
- catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
- } else {
- f5u011_mchash_async(catc, catc->multicast);
- if (catc->rxmode[0] != rx) {
- catc->rxmode[0] = rx;
- dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0],
- catc->rxmode[1]);
- f5u011_rxmode_async(catc, catc->rxmode);
- }
- }
- }
! /*
! * ioctl's
! */
! static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
! {
! struct catc *catc = dev->priv;
! u32 cmd;
! char tmp[40];
!
! if (get_user(cmd, (u32 *)useraddr))
! return -EFAULT;
!
! switch (cmd) {
! /* get driver info */
! case ETHTOOL_GDRVINFO: {
! struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
! strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
! strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
! sprintf(tmp, "usb%d:%d", catc->usbdev->bus->busnum, catc->usbdev->devnum);
! strncpy(info.bus_info, tmp,ETHTOOL_BUSINFO_LEN);
! if (copy_to_user(useraddr, &info, sizeof(info)))
! return -EFAULT;
! return 0;
! }
!
! /* get settings */
! case ETHTOOL_GSET:
! if (catc->is_f5u011) {
! struct ethtool_cmd ecmd = {
! ETHTOOL_GSET,
! SUPPORTED_10baseT_Half | SUPPORTED_TP,
! ADVERTISED_10baseT_Half | ADVERTISED_TP,
! SPEED_10,
! DUPLEX_HALF,
! PORT_TP,
! 0,
! XCVR_INTERNAL,
! AUTONEG_DISABLE,
! 1,
! 1
! };
! if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
! return -EFAULT;
! return 0;
! } else {
! return -EOPNOTSUPP;
! }
! /* get link status */
! case ETHTOOL_GLINK: {
! struct ethtool_value edata = {ETHTOOL_GLINK};
! edata.data = netif_carrier_ok(dev);
! if (copy_to_user(useraddr, &edata, sizeof(edata)))
! return -EFAULT;
! return 0;
! }
! }
! /* Note that the ethtool user space code requires EOPNOTSUPP */
! return -EOPNOTSUPP;
! }
!
! static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
! {
! switch(cmd) {
! case SIOCETHTOOL:
! return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
! default:
! return -ENOTTY; /* Apparently this is the standard ioctl errno */
! }
}
-
/*
* Open, close.
*/
--- 550,568 ----
if (netdev->flags & IFF_PROMISC) {
memset(catc->multicast, 0xff, 64);
! rx |= RxPromisc;
}
! if (netdev->flags & IFF_ALLMULTI)
memset(catc->multicast, 0xff, 64);
! for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next)
! catc_multicast(mc->dmi_addr, catc->multicast);
! catc_set_reg_async(catc, RxUnit, rx);
! catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
}
/*
* Open, close.
*/
***************
*** 747,754 ****
netif_start_queue(netdev);
! if (!catc->is_f5u011)
! mod_timer(&catc->timer, jiffies + STATS_UPDATE);
return 0;
}
--- 580,586 ----
netif_start_queue(netdev);
! mod_timer(&catc->timer, jiffies + STATS_UPDATE);
return 0;
}
***************
*** 759,766 ****
netif_stop_queue(netdev);
! if (!catc->is_f5u011)
! del_timer_sync(&catc->timer);
usb_unlink_urb(&catc->rx_urb);
usb_unlink_urb(&catc->tx_urb);
--- 591,597 ----
netif_stop_queue(netdev);
! del_timer_sync(&catc->timer);
usb_unlink_urb(&catc->rx_urb);
usb_unlink_urb(&catc->tx_urb);
***************
*** 779,785 ****
struct net_device *netdev;
struct catc *catc;
u8 broadcast[6];
! int i, pktsz;
if (usb_set_interface(usbdev, ifnum, 1)) {
err("Can't set altsetting 1.");
--- 610,616 ----
struct net_device *netdev;
struct catc *catc;
u8 broadcast[6];
! int i;
if (usb_set_interface(usbdev, ifnum, 1)) {
err("Can't set altsetting 1.");
***************
*** 787,802 ****
}
catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
- if (!catc)
- return NULL;
-
memset(catc, 0, sizeof(struct catc));
netdev = init_etherdev(0, 0);
- if (!netdev) {
- kfree(catc);
- return NULL;
- }
netdev->open = catc_open;
netdev->hard_start_xmit = catc_hard_start_xmit;
--- 618,626 ----
***************
*** 805,811 ****
netdev->tx_timeout = catc_tx_timeout;
netdev->watchdog_timeo = TX_TIMEOUT;
netdev->set_multicast_list = catc_set_multicast_list;
- netdev->do_ioctl = catc_ioctl;
netdev->priv = catc;
catc->usbdev = usbdev;
--- 629,634 ----
***************
*** 818,837 ****
catc->timer.data = (long) catc;
catc->timer.function = catc_stats_timer;
- /* The F5U011 has the same vendor/product as the netmate
- * but a device version of 0x130
- */
- if (usbdev->descriptor.idVendor == 0x0423 &&
- usbdev->descriptor.idProduct == 0xa &&
- catc->usbdev->descriptor.bcdDevice == 0x0130) {
- dbg("Testing for f5u011");
- catc->is_f5u011 = 1;
- atomic_set(&catc->recq_sz, 0);
- pktsz = RX_PKT_SZ;
- } else {
- pktsz = RX_MAX_BURST * (PKT_SZ + 2);
- }
-
FILL_CONTROL_URB(&catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
NULL, NULL, 0, catc_ctrl_done, catc);
--- 641,646 ----
***************
*** 839,859 ****
NULL, 0, catc_tx_done, catc);
FILL_BULK_URB(&catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
! catc->rx_buf, pktsz, catc_rx_done, catc);
FILL_INT_URB(&catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1);
! if (!catc->is_f5u011) {
! dbg("Checking memory size\n");
! i = 0x12345678;
! catc_write_mem(catc, 0x7a80, &i, 4);
! i = 0x87654321;
! catc_write_mem(catc, 0xfa80, &i, 4);
! catc_read_mem(catc, 0x7a80, &i, 4);
!
! switch (i) {
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
--- 648,667 ----
NULL, 0, catc_tx_done, catc);
FILL_BULK_URB(&catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
! catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc);
FILL_INT_URB(&catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1);
! dbg("Checking memory size\n");
!
! i = 0x12345678;
! catc_write_mem(catc, 0x7a80, &i, 4);
! i = 0x87654321;
! catc_write_mem(catc, 0xfa80, &i, 4);
! catc_read_mem(catc, 0x7a80, &i, 4);
! switch (i) {
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
***************
*** 866,917 ****
catc_set_reg(catc, RxBufCount, 16);
dbg("32k Memory\n");
break;
- }
-
- dbg("Getting MAC from SEEROM.");
-
- catc_get_mac(catc, netdev->dev_addr);
-
- dbg("Setting MAC into registers.");
-
- for (i = 0; i < 6; i++)
- catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
-
- dbg("Filling the multicast list.");
-
- memset(broadcast, 0xff, 6);
- catc_multicast(broadcast, catc->multicast);
- catc_multicast(netdev->dev_addr, catc->multicast);
- catc_write_mem(catc, 0xfa80, catc->multicast, 64);
-
- dbg("Clearing error counters.");
-
- for (i = 0; i < 8; i++)
- catc_set_reg(catc, EthStats + i, 0);
- catc->last_stats = jiffies;
-
- dbg("Enabling.");
-
- catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
- catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
- catc_set_reg(catc, LEDCtrl, LEDLink);
- catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
- } else {
- dbg("Performing reset\n");
- catc_reset(catc);
- catc_get_mac(catc, netdev->dev_addr);
-
- dbg("Setting RX Mode");
- catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
- catc->rxmode[1] = 0;
- f5u011_rxmode(catc, catc->rxmode);
}
dbg("Init done.");
! printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
! netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
! usbdev->bus->busnum, usbdev->devnum, ifnum);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]);
return catc;
}
--- 674,717 ----
catc_set_reg(catc, RxBufCount, 16);
dbg("32k Memory\n");
break;
}
+
+ dbg("Getting MAC from SEEROM.");
+
+ catc_get_mac(catc, netdev->dev_addr);
+
+ dbg("Setting MAC into registers.");
+
+ for (i = 0; i < 6; i++)
+ catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
+
+ dbg("Filling the multicast list.");
+
+ memset(broadcast, 0xff, 8);
+ catc_multicast(broadcast, catc->multicast);
+ catc_multicast(netdev->dev_addr, catc->multicast);
+ catc_write_mem(catc, 0xfa80, catc->multicast, 64);
+
+ dbg("Clearing error counters.");
+
+ for (i = 0; i < 8; i++)
+ catc_set_reg(catc, EthStats + i, 0);
+ catc->last_stats = jiffies;
+
+ dbg("Enabling.");
+
+ catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
+ catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
+ catc_set_reg(catc, LEDCtrl, LEDLink);
+ catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
+
dbg("Init done.");
!
! printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ",
! netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]);
+
return catc;
}
***************
*** 928,934 ****
*/
static struct usb_device_id catc_id_table [] = {
! { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate, Belkin F5U011 */
{ USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */
{ USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */
{ }
--- 728,734 ----
*/
static struct usb_device_id catc_id_table [] = {
! { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */
{ USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */
{ USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */
{ }
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/dabusb.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/dabusb.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/dabusb.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/dabusb.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 83,89 ****
}
/*-------------------------------------------------------------------*/
#ifdef DEBUG
! static void dump_urb (struct urb *purb)
{
dbg("urb :%p", purb);
dbg("next :%p", purb->next);
--- 83,89 ----
}
/*-------------------------------------------------------------------*/
#ifdef DEBUG
! static void dump_urb (purb_t purb)
{
dbg("urb :%p", purb);
dbg("next :%p", purb->next);
***************
*** 167,173 ****
return 0;
}
/*-------------------------------------------------------------------*/
! static void dabusb_iso_complete (struct urb *purb)
{
pbuff_t b = purb->context;
pdabusb_t s = b->s;
--- 167,173 ----
return 0;
}
/*-------------------------------------------------------------------*/
! static void dabusb_iso_complete (purb_t purb)
{
pbuff_t b = purb->context;
pdabusb_t s = b->s;
***************
*** 482,488 ****
int rem;
int cnt;
pbuff_t b;
! struct urb *purb = NULL;
dbg("dabusb_read");
--- 482,488 ----
int rem;
int cnt;
pbuff_t b;
! purb_t purb = NULL;
dbg("dabusb_read");
***************
*** 605,611 ****
}
if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
err("set_interface failed");
- up(&s->mutex);
return -EINVAL;
}
s->opened = 1;
--- 605,610 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/dabusb.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/dabusb.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/dabusb.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/dabusb.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 38,44 ****
typedef struct
{
pdabusb_t s;
! struct urb *purb;
struct list_head buff_list;
} buff_t,*pbuff_t;
--- 38,44 ----
typedef struct
{
pdabusb_t s;
! purb_t purb;
struct list_head buff_list;
} buff_t,*pbuff_t;
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/devices.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/devices.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/devices.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/devices.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 61,68 ****
#include
#include
- #include "hcd.h"
-
#define MAX_TOPO_LEVEL 6
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
--- 61,66 ----
***************
*** 107,114 ****
"I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
static char *format_endpt =
! /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
! "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
/*
--- 105,112 ----
"I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
static char *format_endpt =
! /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
! "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
/*
***************
*** 168,240 ****
return (clas_info[ix].class_name);
}
! static char *usb_dump_endpoint_descriptor (
! int speed,
! char *start,
! char *end,
! const struct usb_endpoint_descriptor *desc
! )
! {
! char dir, unit, *type;
! unsigned interval, in, bandwidth = 1;
if (start > end)
return start;
! in = (desc->bEndpointAddress & USB_DIR_IN);
! dir = in ? 'I' : 'O';
! if (speed == USB_SPEED_HIGH) {
! switch (desc->wMaxPacketSize & (0x03 << 11)) {
! case 1 << 11: bandwidth = 2; break;
! case 2 << 11: bandwidth = 3; break;
! }
! }
!
! /* this isn't checking for illegal values */
! switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
! case USB_ENDPOINT_XFER_CONTROL:
! type = "Ctrl";
! if (speed == USB_SPEED_HIGH) /* uframes per NAK */
! interval = desc->bInterval;
! else
! interval = 0;
! dir = 'B'; /* ctrl is bidirectional */
! break;
! case USB_ENDPOINT_XFER_ISOC:
! type = "Isoc";
! interval = 1 << (desc->bInterval - 1);
! break;
! case USB_ENDPOINT_XFER_BULK:
! type = "Bulk";
! if (speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
! interval = desc->bInterval;
! else
! interval = 0;
! break;
! case USB_ENDPOINT_XFER_INT:
! type = "Int.";
! if (speed == USB_SPEED_HIGH) {
! interval = 1 << (desc->bInterval - 1);
! } else
! interval = desc->bInterval;
! break;
! default: /* "can't happen" */
! return start;
! }
! interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
! if (interval % 1000)
! unit = 'u';
! else {
! unit = 'm';
! interval /= 1000;
! }
!
! start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
! desc->bmAttributes, type,
! (desc->wMaxPacketSize & 0x07ff) * bandwidth,
! interval, unit);
return start;
}
static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
{
struct usb_interface_descriptor *desc = &iface->altsetting[setno];
--- 166,191 ----
return (clas_info[ix].class_name);
}
! static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct usb_endpoint_descriptor *desc)
! {
! char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
if (start > end)
return start;
! start += sprintf(start, format_endpt, desc->bEndpointAddress,
! (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL
! ? 'B' : /* bidirectional */
! (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
! desc->bmAttributes, EndpointType[desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK],
! desc->wMaxPacketSize, desc->bInterval);
return start;
}
+ static char *usb_dump_endpoint(char *start, char *end, const struct usb_endpoint_descriptor *endpoint)
+ {
+ return usb_dump_endpoint_descriptor(start, end, endpoint);
+ }
+
static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
{
struct usb_interface_descriptor *desc = &iface->altsetting[setno];
***************
*** 253,265 ****
return start;
}
! static char *usb_dump_interface(
! int speed,
! char *start,
! char *end,
! const struct usb_interface *iface,
! int setno
! ) {
struct usb_interface_descriptor *desc = &iface->altsetting[setno];
int i;
--- 204,211 ----
return start;
}
! static char *usb_dump_interface(char *start, char *end, const struct usb_interface *iface, int setno)
! {
struct usb_interface_descriptor *desc = &iface->altsetting[setno];
int i;
***************
*** 267,274 ****
for (i = 0; i < desc->bNumEndpoints; i++) {
if (start > end)
return start;
! start = usb_dump_endpoint_descriptor(speed,
! start, end, desc->endpoint + i);
}
return start;
}
--- 213,219 ----
for (i = 0; i < desc->bNumEndpoints; i++) {
if (start > end)
return start;
! start = usb_dump_endpoint(start, end, desc->endpoint + i);
}
return start;
}
***************
*** 293,305 ****
return start;
}
! static char *usb_dump_config (
! int speed,
! char *start,
! char *end,
! const struct usb_config_descriptor *config,
! int active
! )
{
int i, j;
struct usb_interface *interface;
--- 238,244 ----
return start;
}
! static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, int active)
{
int i, j;
struct usb_interface *interface;
***************
*** 316,323 ****
for (j = 0; j < interface->num_altsetting; j++) {
if (start > end)
return start;
! start = usb_dump_interface(speed,
! start, end, interface, j);
}
}
return start;
--- 255,261 ----
for (j = 0; j < interface->num_altsetting; j++) {
if (start > end)
return start;
! start = usb_dump_interface(start, end, interface, j);
}
}
return start;
***************
*** 398,407 ****
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
if (start > end)
return start;
! start = usb_dump_config(dev->speed,
! start, end, dev->config + i,
! /* active ? */
! (dev->config + i) == dev->actconfig);
}
return start;
}
--- 336,343 ----
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
if (start > end)
return start;
! start = usb_dump_config(start, end, dev->config + i,
! (dev->config + i) == dev->actconfig); /* active ? */
}
return start;
}
***************
*** 493,518 ****
* count = device count at this level
*/
/* If this is the root hub, display the bandwidth information */
! if (level == 0) {
! int max;
!
! /* high speed reserves 80%, full/low reserves 90% */
! if (usbdev->speed == USB_SPEED_HIGH)
! max = 800;
! else
! max = FRAME_TIME_MAX_USECS_ALLOC;
!
! /* report "average" periodic allocation over a microsecond.
! * the schedules are actually bursty, HCDs need to deal with
! * that and just compute/report this average.
! */
! data_end += sprintf(data_end, format_bandwidth,
! bus->bandwidth_allocated, max,
! (100 * bus->bandwidth_allocated + max / 2)
! / max,
! bus->bandwidth_int_reqs,
! bus->bandwidth_isoc_reqs);
! }
data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
--- 429,440 ----
* count = device count at this level
*/
/* If this is the root hub, display the bandwidth information */
! if (level == 0)
! data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated,
! FRAME_TIME_MAX_USECS_ALLOC,
! (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
! bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
!
data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
***************
*** 575,584 ****
bus = list_entry(buslist, struct usb_bus, bus_list);
/* recurse through all children of the root hub */
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
! if (ret < 0) {
! up(&usb_bus_list_lock);
return ret;
- }
total_written += ret;
}
up (&usb_bus_list_lock);
--- 497,504 ----
bus = list_entry(buslist, struct usb_bus, bus_list);
/* recurse through all children of the root hub */
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
! if (ret < 0)
return ret;
total_written += ret;
}
up (&usb_bus_list_lock);
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/devio.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/devio.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/devio.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/devio.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 52,58 ****
unsigned int signr;
void *userbuffer;
void *userurb;
! struct urb urb;
};
static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
--- 52,58 ----
unsigned int signr;
void *userbuffer;
void *userurb;
! urb_t urb;
};
static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
***************
*** 138,144 ****
return ret;
}
! static inline unsigned int ld2(unsigned int x)
{
unsigned int r = 0;
--- 138,144 ----
return ret;
}
! extern inline unsigned int ld2(unsigned int x)
{
unsigned int r = 0;
***************
*** 169,175 ****
static struct async *alloc_async(unsigned int numisoframes)
{
! unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct iso_packet_descriptor);
struct async *as = kmalloc(assize, GFP_KERNEL);
if (!as)
return NULL;
--- 169,175 ----
static struct async *alloc_async(unsigned int numisoframes)
{
! unsigned int assize = sizeof(struct async) + numisoframes * sizeof(iso_packet_descriptor_t);
struct async *as = kmalloc(assize, GFP_KERNEL);
if (!as)
return NULL;
***************
*** 188,194 ****
kfree(as);
}
! static inline void async_newpending(struct async *as)
{
struct dev_state *ps = as->ps;
unsigned long flags;
--- 188,194 ----
kfree(as);
}
! extern __inline__ void async_newpending(struct async *as)
{
struct dev_state *ps = as->ps;
unsigned long flags;
***************
*** 198,204 ****
spin_unlock_irqrestore(&ps->lock, flags);
}
! static inline void async_removepending(struct async *as)
{
struct dev_state *ps = as->ps;
unsigned long flags;
--- 198,204 ----
spin_unlock_irqrestore(&ps->lock, flags);
}
! extern __inline__ void async_removepending(struct async *as)
{
struct dev_state *ps = as->ps;
unsigned long flags;
***************
*** 209,215 ****
spin_unlock_irqrestore(&ps->lock, flags);
}
! static inline struct async *async_getcompleted(struct dev_state *ps)
{
unsigned long flags;
struct async *as = NULL;
--- 209,215 ----
spin_unlock_irqrestore(&ps->lock, flags);
}
! extern __inline__ struct async *async_getcompleted(struct dev_state *ps)
{
unsigned long flags;
struct async *as = NULL;
***************
*** 224,230 ****
return as;
}
! static inline struct async *async_getpending(struct dev_state *ps, void *userurb)
{
unsigned long flags;
struct async *as;
--- 224,230 ----
return as;
}
! extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb)
{
unsigned long flags;
struct async *as;
***************
*** 245,251 ****
return NULL;
}
! static void async_completed(struct urb *urb)
{
struct async *as = (struct async *)urb->context;
struct dev_state *ps = as->ps;
--- 245,251 ----
return NULL;
}
! static void async_completed(purb_t urb)
{
struct async *as = (struct async *)urb->context;
struct dev_state *ps = as->ps;
***************
*** 286,294 ****
}
/*
! * interface claims are made only at the request of user level code,
! * which can also release them (explicitly or by closing files).
! * they're also undone when devices disconnect.
*/
static void *driver_probe(struct usb_device *dev, unsigned int intf,
--- 286,292 ----
}
/*
! * interface claiming
*/
static void *driver_probe(struct usb_device *dev, unsigned int intf,
***************
*** 301,320 ****
{
struct dev_state *ps = (struct dev_state *)context;
- if (!ps)
- return;
-
- /* this waits till synchronous requests complete */
- down_write (&ps->devsem);
-
- /* prevent new I/O requests */
- ps->dev = 0;
ps->ifclaimed = 0;
-
- /* force async requests to complete */
- destroy_all_async (ps);
-
- up_write (&ps->devsem);
}
struct usb_driver usbdevfs_driver = {
--- 299,305 ----
***************
*** 772,778 ****
struct usbdevfs_iso_packet_desc *isopkt = NULL;
struct usb_endpoint_descriptor *ep_desc;
struct async *as;
! struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
int ret;
--- 757,763 ----
struct usbdevfs_iso_packet_desc *isopkt = NULL;
struct usb_endpoint_descriptor *ep_desc;
struct async *as;
! devrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
int ret;
***************
*** 802,824 ****
/* min 8 byte setup packet, max arbitrary */
if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
return -EINVAL;
! if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
return -ENOMEM;
if (copy_from_user(dr, (unsigned char*)uurb.buffer, 8)) {
kfree(dr);
return -EFAULT;
}
! if (uurb.buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
kfree(dr);
return -EINVAL;
}
! if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)))) {
kfree(dr);
return ret;
}
! uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
uurb.number_of_packets = 0;
! uurb.buffer_length = le16_to_cpup(&dr->wLength);
uurb.buffer += 8;
if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
kfree(dr);
--- 787,809 ----
/* min 8 byte setup packet, max arbitrary */
if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
return -EINVAL;
! if (!(dr = kmalloc(sizeof(devrequest), GFP_KERNEL)))
return -ENOMEM;
if (copy_from_user(dr, (unsigned char*)uurb.buffer, 8)) {
kfree(dr);
return -EFAULT;
}
! if (uurb.buffer_length < (le16_to_cpup(&dr->length) + 8)) {
kfree(dr);
return -EINVAL;
}
! if ((ret = check_ctrlrecip(ps, dr->requesttype, le16_to_cpup(&dr->index)))) {
kfree(dr);
return ret;
}
! uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->requesttype & USB_ENDPOINT_DIR_MASK);
uurb.number_of_packets = 0;
! uurb.buffer_length = le16_to_cpup(&dr->length);
uurb.buffer += 8;
if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
kfree(dr);
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: emi26.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: emi26_fw.h
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hc_simple.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hc_simple.h
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hc_sl811.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hc_sl811.h
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hc_sl811_rh.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hcd
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hcd.c
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: hcd.h
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hid-core.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hid-core.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hid-core.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hid-core.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 47,59 ****
#include
#include "hid.h"
#include
/*
* Version Information
*/
! #define DRIVER_VERSION "v1.8.1"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik "
#define DRIVER_DESC "USB HID support drivers"
--- 47,61 ----
#include
#include "hid.h"
+ #ifdef CONFIG_USB_HIDDEV
#include
+ #endif
/*
* Version Information
*/
! #define DRIVER_VERSION "v1.8"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik "
#define DRIVER_DESC "USB HID support drivers"
***************
*** 202,214 ****
return -1;
}
! if (parser->global.logical_maximum <= parser->global.logical_minimum) {
! dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
! return -1;
}
- usages = parser->local.usage_index;
-
offset = report->size;
report->size += parser->global.report_size * parser->global.report_count;
--- 204,220 ----
return -1;
}
! if (HID_MAIN_ITEM_VARIABLE & ~flags) { /* ARRAY */
! if (parser->global.logical_maximum <= parser->global.logical_minimum) {
! dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
! return -1;
! }
! usages = parser->local.usage_index;
! /* Hint: we can assume usages < MAX_USAGE here */
! } else { /* VARIABLE */
! usages = parser->global.report_count;
}
offset = report->size;
report->size += parser->global.report_size * parser->global.report_count;
***************
*** 304,313 ****
return 0;
case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
! if (parser->global.logical_minimum < 0)
! parser->global.logical_maximum = item_sdata(item);
! else
! parser->global.logical_maximum = item_udata(item);
return 0;
case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
--- 310,316 ----
return 0;
case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
! parser->global.logical_maximum = item_sdata(item);
return 0;
case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
***************
*** 315,324 ****
return 0;
case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
! if (parser->global.physical_minimum < 0)
! parser->global.physical_maximum = item_sdata(item);
! else
! parser->global.physical_maximum = item_udata(item);
return 0;
case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
--- 318,324 ----
return 0;
case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
! parser->global.physical_maximum = item_sdata(item);
return 0;
case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
***************
*** 735,742 ****
--- 735,744 ----
hid_dump_input(usage, value);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value);
+ #ifdef CONFIG_USB_HIDDEV
if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_hid_event(hid, usage->hid, value);
+ #endif
}
***************
*** 895,903 ****
u8 data[len];
int read;
- if (hid->quirks & HID_QUIRK_NOGET)
- return;
-
if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
dbg("reading report type %d id %d failed len %d read %d", report->type + 1, report->id, len, read);
return;
--- 897,902 ----
***************
*** 988,994 ****
static int hid_submit_out(struct hid_device *hid)
{
! hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.wLength);
hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer;
hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
hid->urbout.dev = hid->dev;
--- 987,993 ----
static int hid_submit_out(struct hid_device *hid)
{
! hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.length);
hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer;
hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
hid->urbout.dev = hid->dev;
***************
*** 1018,1025 ****
{
hid_output_report(report, hid->out[hid->outhead].buffer);
! hid->out[hid->outhead].dr.wValue = cpu_to_le16(0x200 | report->id);
! hid->out[hid->outhead].dr.wLength = cpu_to_le16((report->size + 7) >> 3);
hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1);
--- 1017,1024 ----
{
hid_output_report(report, hid->out[hid->outhead].buffer);
! hid->out[hid->outhead].dr.value = cpu_to_le16(0x200 | report->id);
! hid->out[hid->outhead].dr.length = cpu_to_le16((report->size + 7) >> 3);
hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1);
***************
*** 1065,1072 ****
list = report_enum->report_list.next;
while (list != &report_enum->report_list) {
report = (struct hid_report *) list;
- hid_read_report(hid, report);
usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
list = list->next;
}
}
--- 1064,1071 ----
list = report_enum->report_list.next;
while (list != &report_enum->report_list) {
report = (struct hid_report *) list;
usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
+ hid_read_report(hid, report);
list = list->next;
}
}
***************
*** 1074,1120 ****
}
#define USB_VENDOR_ID_WACOM 0x056a
- #define USB_DEVICE_ID_WACOM_PENPARTNER 0x0000
#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
- #define USB_DEVICE_ID_WACOM_PL 0x0030
- #define USB_DEVICE_ID_WACOM_INTUOS2 0x0041
-
- #define USB_VENDOR_ID_ATEN 0x0557
- #define USB_DEVICE_ID_ATEN_UC100KM 0x2004
- #define USB_DEVICE_ID_ATEN_CS124U 0x2202
- #define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
- #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
- unsigned quirks;
} hid_blacklist[] = {
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
! { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
! { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
! { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
! { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ 0, 0 }
};
--- 1073,1091 ----
}
#define USB_VENDOR_ID_WACOM 0x056a
#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
} hid_blacklist[] = {
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS },
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1},
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2},
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3},
! { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4},
{ 0, 0 }
};
***************
*** 1123,1139 ****
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
struct hid_descriptor *hdesc;
struct hid_device *hid;
! unsigned quirks = 0, rsize = 0;
char *buf;
int n;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
! (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
! quirks = hid_blacklist[n].quirks;
!
! if (quirks & HID_QUIRK_IGNORE)
! return NULL;
if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc))) {
--- 1094,1106 ----
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
struct hid_descriptor *hdesc;
struct hid_device *hid;
! unsigned rsize = 0;
char *buf;
int n;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
! (hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL;
if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc))) {
***************
*** 1171,1178 ****
}
}
- hid->quirks = quirks;
-
for (n = 0; n < interface->bNumEndpoints; n++) {
struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
--- 1138,1143 ----
***************
*** 1204,1212 ****
hid->ifnum = interface->bInterfaceNumber;
for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
! hid->out[n].dr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
! hid->out[n].dr.bRequest = USB_REQ_SET_REPORT;
! hid->out[n].dr.wIndex = cpu_to_le16(hid->ifnum);
}
hid->name[0] = 0;
--- 1169,1177 ----
hid->ifnum = interface->bInterfaceNumber;
for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
! hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
! hid->out[n].dr.request = USB_REQ_SET_REPORT;
! hid->out[n].dr.index = cpu_to_le16(hid->ifnum);
}
hid->name[0] = 0;
***************
*** 1256,1263 ****
--- 1221,1230 ----
if (!hidinput_connect(hid))
hid->claimed |= HID_CLAIMED_INPUT;
+ #ifdef CONFIG_USB_HIDDEV
if (!hiddev_connect(hid))
hid->claimed |= HID_CLAIMED_HIDDEV;
+ #endif
printk(KERN_INFO);
if (hid->claimed & HID_CLAIMED_INPUT)
***************
*** 1287,1296 ****
--- 1254,1266 ----
dbg("cleanup called");
usb_unlink_urb(&hid->urb);
+
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid);
+ #ifdef CONFIG_USB_HIDDEV
if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_disconnect(hid);
+ #endif
hid_free_device(hid);
}
***************
*** 1311,1317 ****
--- 1281,1289 ----
static int __init hid_init(void)
{
+ #ifdef CONFIG_USB_HIDDEV
hiddev_init();
+ #endif
usb_register(&hid_driver);
info(DRIVER_VERSION " " DRIVER_AUTHOR);
info(DRIVER_DESC);
***************
*** 1321,1327 ****
--- 1293,1301 ----
static void __exit hid_exit(void)
{
+ #ifdef CONFIG_USB_HIDDEV
hiddev_exit();
+ #endif
usb_deregister(&hid_driver);
}
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hid.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hid.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hid.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hid.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 184,191 ****
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
- #define HID_QUIRK_IGNORE 0x04
- #define HID_QUIRK_NOGET 0x08
/*
* This is the global enviroment of the parser. This information is
--- 184,189 ----
***************
*** 287,293 ****
#define HID_CONTROL_FIFO_SIZE 8
struct hid_control_fifo {
! struct usb_ctrlrequest dr;
char buffer[HID_BUFFER_SIZE];
};
--- 285,291 ----
#define HID_CONTROL_FIFO_SIZE 8
struct hid_control_fifo {
! devrequest dr;
char buffer[HID_BUFFER_SIZE];
};
***************
*** 352,357 ****
--- 350,358 ----
struct hid_class_descriptor desc[1];
} __attribute__ ((packed));
+ void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
+ int hidinput_connect(struct hid_device *);
+ void hidinput_disconnect(struct hid_device *);
#ifdef DEBUG
#include "hid-debug.h"
***************
*** 362,378 ****
#endif
- #ifdef CONFIG_USB_HIDINPUT
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || ( a == 0x000c0001))
- extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
- extern int hidinput_connect(struct hid_device *);
- extern void hidinput_disconnect(struct hid_device *);
- #else
- #define IS_INPUT_APPLICATION(a) (0)
- static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
- static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
- static inline void hidinput_disconnect(struct hid_device *hid) { }
- #endif
int hid_open(struct hid_device *);
void hid_close(struct hid_device *);
--- 363,369 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hpusbscsi.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hpusbscsi.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hpusbscsi.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hpusbscsi.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,51 ****
- /*
- * hpusbscsi
- * (C) Copyright 2001 Oliver Neukum
- * Sponsored by the Linux Usb Project
- * Large parts based on or taken from code by John Fremlin and Matt Dharm
- *
- * This driver is known to work with the following scanners (VID, PID)
- * (0x03f0, 0x0701) HP 53xx
- * (0x03f0, 0x0801) HP 7400
- * (0x0638, 0x026a) Minolta Scan Dual II
- * (0x0686, 0x4004) Minolta Elite II
- * To load with full debugging load with "insmod hpusbscsi debug=2"
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Contributors:
- * Oliver Neukum
- * John Fremlin
- * Matt Dharm
- * .
- * .
- * Timothy Jedlicka
- *
- * History
- *
- * 22-Apr-2002
- *
- * - Added Elite II scanner - bonzo
- * - Cleaned up the debug statements and made them optional at load time - bonzo
- *
- * 20020618
- *
- * - Confirm to stupid 2.4 rules on io_request_lock
- *
- */
-
#include
#include
#include
--- 1,3 ----
***************
*** 64,91 ****
#include "hpusbscsi.h"
! static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
!
! /* DEBUG related parts */
! #define HPUSBSCSI_DEBUG
! #ifdef HPUSBSCSI_DEBUG
! # define PDEBUG(level, fmt, args...) \
! if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , \
! ## args)
! #else
! # define PDEBUG(level, fmt, args...) do {} while(0)
! #endif
!
!
! /* 0=no debug messages
! * 1=everything but trace states
! * 2=trace states
! */
! static int debug; /* = 0 */
! MODULE_PARM(debug, "i");
! MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=no trace states, 2=trace states");
/* global variables */
--- 16,27 ----
#include "hpusbscsi.h"
! #define DEBUG(x...) \
! printk( KERN_DEBUG x )
! static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
! #define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
/* global variables */
***************
*** 118,124 ****
GFP_KERNEL);
if (new == NULL)
return NULL;
! PDEBUG (1, "Allocated memory");
memset (new, 0, sizeof (struct hpusbscsi));
spin_lock_init (&new->dataurb.lock);
spin_lock_init (&new->controlurb.lock);
--- 54,60 ----
GFP_KERNEL);
if (new == NULL)
return NULL;
! DEBUG ("Allocated memory\n");
memset (new, 0, sizeof (struct hpusbscsi));
spin_lock_init (&new->dataurb.lock);
spin_lock_init (&new->controlurb.lock);
***************
*** 184,192 ****
if (scsi_register_module (MODULE_SCSI_HA, &(new->ctempl)))
goto err_out;
- new->sense_command[0] = REQUEST_SENSE;
- new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
-
/* adding to list for module unload */
list_add (&hpusbscsi_devices, &new->lh);
--- 120,125 ----
***************
*** 200,226 ****
static void
hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
{
! struct hpusbscsi *hp = (struct hpusbscsi *)ptr;
!
! usb_unlink_urb(&hp->controlurb);
! usb_unlink_urb(&hp->dataurb);
!
! spin_lock_irq(&io_request_lock);
! hp->dev = NULL;
! spin_unlock_irq(&io_request_lock);
}
static struct usb_device_id hpusbscsi_usb_ids[] = {
{USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */
{USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */
- {USB_DEVICE (0x0638, 0x0268)}, /*iVina 1200U */
{USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */
- {USB_DEVICE (0x0638, 0x0A13)}, /*Avision AV600U */
- {USB_DEVICE (0x0638, 0x0A16)}, /*Avision DS610CU Scancopier */
- {USB_DEVICE (0x0638, 0x0A18)}, /*Avision AV600U Plus */
- {USB_DEVICE (0x0638, 0x0A23)}, /*Avision AV220 */
- {USB_DEVICE (0x0638, 0x0A24)}, /*Avision AV210 */
- {USB_DEVICE (0x0686, 0x4004)}, /*Minolta Elite II */
{} /* Terminating entry */
};
--- 133,146 ----
static void
hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
{
! usb_unlink_urb(&(((struct hpusbscsi *) ptr)->controlurb));
! ((struct hpusbscsi *) ptr)->dev = NULL;
}
static struct usb_device_id hpusbscsi_usb_ids[] = {
{USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */
{USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */
{USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */
{} /* Terminating entry */
};
***************
*** 243,250 ****
int result;
INIT_LIST_HEAD (&hpusbscsi_devices);
! PDEBUG(0, "driver loaded, DebugLvel=%d", debug);
!
if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
printk (KERN_ERR "hpusbscsi: driver registration failed\n");
return -1;
--- 163,170 ----
int result;
INIT_LIST_HEAD (&hpusbscsi_devices);
! DEBUG ("Driver loaded\n");
!
if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
printk (KERN_ERR "hpusbscsi: driver registration failed\n");
return -1;
***************
*** 265,272 ****
tmp = tmp->next;
o = (struct hpusbscsi *)old;
usb_unlink_urb(&o->controlurb);
! if(scsi_unregister_module(MODULE_SCSI_HA,&o->ctempl)<0)
! printk(KERN_CRIT"Deregistering failed!\n");
kfree(old);
}
--- 185,191 ----
tmp = tmp->next;
o = (struct hpusbscsi *)old;
usb_unlink_urb(&o->controlurb);
! scsi_unregister_module(MODULE_SCSI_HA,&o->ctempl);
kfree(old);
}
***************
*** 287,293 ****
/* What a hideous hack! */
char local_name[48];
- spin_unlock_irq(&io_request_lock);
/* set up the name of our subdirectory under /proc/scsi/ */
--- 206,211 ----
***************
*** 296,302 ****
/* FIXME: where is this freed ? */
if (!sht->proc_name) {
- spin_lock_irq(&io_request_lock);
return 0;
}
--- 214,219 ----
***************
*** 317,323 ****
if ( 0 > usb_submit_urb(&desc->controlurb)) {
kfree(sht->proc_name);
- spin_lock_irq(&io_request_lock);
return 0;
}
--- 234,239 ----
***************
*** 326,336 ****
if (desc->host == NULL) {
kfree (sht->proc_name);
usb_unlink_urb(&desc->controlurb);
- spin_lock_irq(&io_request_lock);
return 0;
}
desc->host->hostdata[0] = (unsigned long) desc;
! spin_lock_irq(&io_request_lock);
return 1;
}
--- 242,251 ----
if (desc->host == NULL) {
kfree (sht->proc_name);
usb_unlink_urb(&desc->controlurb);
return 0;
}
desc->host->hostdata[0] = (unsigned long) desc;
!
return 1;
}
***************
*** 341,365 ****
usb_urb_callback usb_callback;
int res;
! spin_unlock_irq(&io_request_lock);
/* we don't answer for anything but our single device on any faked host controller */
if ( srb->device->lun || srb->device->id || srb->device->channel ) {
! srb->result = DID_BAD_TARGET;
! callback(srb);
! goto out;
}
/* Now we need to decide which callback to give to the urb we send the command with */
if (!srb->bufflen) {
! if (srb->cmnd[0] == REQUEST_SENSE){
! /* the usual buffer is not used, needs a special case */
! hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
! usb_callback = request_sense_callback;
! } else {
! usb_callback = simple_command_callback;
! }
} else {
if (srb->use_sg) {
usb_callback = scatter_gather_callback;
--- 256,276 ----
usb_urb_callback usb_callback;
int res;
! hpusbscsi->use_count++;
/* we don't answer for anything but our single device on any faked host controller */
if ( srb->device->lun || srb->device->id || srb->device->channel ) {
! if (callback) {
! srb->result = DID_BAD_TARGET;
! callback(srb);
! }
! goto out;
}
/* Now we need to decide which callback to give to the urb we send the command with */
if (!srb->bufflen) {
! usb_callback = simple_command_callback;
} else {
if (srb->use_sg) {
usb_callback = scatter_gather_callback;
***************
*** 376,382 ****
}
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
if (hpusbscsi->state != HP_STATE_FREE) {
printk(KERN_CRIT"hpusbscsi - Ouch: queueing violation!\n");
return 1; /* This must not happen */
--- 287,293 ----
}
! TRACE_STATE;
if (hpusbscsi->state != HP_STATE_FREE) {
printk(KERN_CRIT"hpusbscsi - Ouch: queueing violation!\n");
return 1; /* This must not happen */
***************
*** 386,392 ****
memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
hpusbscsi->state = HP_STATE_BEGINNING;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
/* We prepare the urb for writing out the scsi command */
FILL_BULK_URB(
--- 297,303 ----
memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
hpusbscsi->state = HP_STATE_BEGINNING;
! TRACE_STATE;
/* We prepare the urb for writing out the scsi command */
FILL_BULK_URB(
***************
*** 400,423 ****
);
hpusbscsi->scallback = callback;
hpusbscsi->srb = srb;
-
- if (hpusbscsi->dev == NULL) {
- srb->result = DID_ERROR;
- callback(srb);
- goto out;
- }
res = usb_submit_urb(&hpusbscsi->dataurb);
if (res) {
hpusbscsi->state = HP_STATE_FREE;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
! srb->result = DID_ERROR;
! callback(srb);
!
}
out:
! spin_lock_irq(&io_request_lock);
return 0;
}
--- 311,329 ----
);
hpusbscsi->scallback = callback;
hpusbscsi->srb = srb;
res = usb_submit_urb(&hpusbscsi->dataurb);
if (res) {
hpusbscsi->state = HP_STATE_FREE;
! TRACE_STATE;
! if (callback) {
! srb->result = DID_ERROR;
! callback(srb);
! }
}
out:
! hpusbscsi->use_count--;
return 0;
}
***************
*** 425,433 ****
{
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
! PDEBUG(1, "SCSI reset requested");
! //usb_reset_device(hpusbscsi->dev);
! //PDEBUG(1, "SCSI reset completed");
hpusbscsi->state = HP_STATE_FREE;
return 0;
--- 331,339 ----
{
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
! printk(KERN_DEBUG"SCSI reset requested.\n");
! usb_reset_device(hpusbscsi->dev);
! printk(KERN_DEBUG"SCSI reset completed.\n");
hpusbscsi->state = HP_STATE_FREE;
return 0;
***************
*** 436,449 ****
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
{
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
! PDEBUG(1, "Request is canceled");
- spin_unlock_irq(&io_request_lock);
usb_unlink_urb(&hpusbscsi->dataurb);
hpusbscsi->state = HP_STATE_FREE;
- spin_lock_irq(&io_request_lock);
-
return SCSI_ABORT_PENDING;
}
--- 342,353 ----
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
{
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
! printk(KERN_DEBUG"Requested is canceled.\n");
usb_unlink_urb(&hpusbscsi->dataurb);
+ usb_unlink_urb(&hpusbscsi->controlurb);
hpusbscsi->state = HP_STATE_FREE;
return SCSI_ABORT_PENDING;
}
***************
*** 461,512 ****
static void control_interrupt_callback (struct urb *u)
{
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- u8 scsi_state;
! PDEBUG(1, "Getting status byte %d",hpusbscsi->scsi_state_byte);
if(u->status < 0) {
if (hpusbscsi->state != HP_STATE_FREE)
handle_usb_error(hpusbscsi);
return;
}
! scsi_state = hpusbscsi->scsi_state_byte;
! if (hpusbscsi->state != HP_STATE_ERROR) {
! hpusbscsi->srb->result &= SCSI_ERR_MASK;
! hpusbscsi->srb->result |= scsi_state;
! }
!
! if (scsi_state == CHECK_CONDITION << 1) {
! if (hpusbscsi->state == HP_STATE_WAIT) {
! issue_request_sense(hpusbscsi);
! } else {
! /* we request sense after an eventual data transfer */
! hpusbscsi->state = HP_STATE_ERROR;
! }
! }
!
! if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1)
/* we do a callback to the scsi layer if and only if all data has been transfered */
hpusbscsi->scallback(hpusbscsi->srb);
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
switch (hpusbscsi->state) {
case HP_STATE_WAIT:
hpusbscsi->state = HP_STATE_FREE;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
break;
case HP_STATE_WORKING:
case HP_STATE_BEGINNING:
hpusbscsi->state = HP_STATE_PREMATURE;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
! break;
! case HP_STATE_ERROR:
break;
default:
printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
hpusbscsi->state = HP_STATE_FREE;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
break;
}
}
--- 365,400 ----
static void control_interrupt_callback (struct urb *u)
{
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
! DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
if(u->status < 0) {
if (hpusbscsi->state != HP_STATE_FREE)
handle_usb_error(hpusbscsi);
return;
}
+ hpusbscsi->srb->result &= SCSI_ERR_MASK;
+ hpusbscsi->srb->result |= hpusbscsi->scsi_state_byte<<1;
! if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT)
/* we do a callback to the scsi layer if and only if all data has been transfered */
hpusbscsi->scallback(hpusbscsi->srb);
! TRACE_STATE;
switch (hpusbscsi->state) {
case HP_STATE_WAIT:
hpusbscsi->state = HP_STATE_FREE;
! TRACE_STATE;
break;
case HP_STATE_WORKING:
case HP_STATE_BEGINNING:
hpusbscsi->state = HP_STATE_PREMATURE;
! TRACE_STATE;
break;
default:
printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
! TRACE_STATE;
hpusbscsi->state = HP_STATE_FREE;
! TRACE_STATE;
break;
}
}
***************
*** 518,532 ****
handle_usb_error(hpusbscsi);
return;
}
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
if (hpusbscsi->state != HP_STATE_PREMATURE) {
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
hpusbscsi->state = HP_STATE_WAIT;
} else {
if (hpusbscsi->scallback != NULL)
hpusbscsi->scallback(hpusbscsi->srb);
hpusbscsi->state = HP_STATE_FREE;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
}
}
--- 406,420 ----
handle_usb_error(hpusbscsi);
return;
}
! TRACE_STATE;
if (hpusbscsi->state != HP_STATE_PREMATURE) {
! TRACE_STATE;
hpusbscsi->state = HP_STATE_WAIT;
} else {
if (hpusbscsi->scallback != NULL)
hpusbscsi->scallback(hpusbscsi->srb);
hpusbscsi->state = HP_STATE_FREE;
! TRACE_STATE;
}
}
***************
*** 537,543 ****
usb_urb_callback callback;
int res;
! PDEBUG(1, "Going through scatter/gather"); // bonzo - this gets hit a lot - maybe make it a 2
if (u->status < 0) {
handle_usb_error(hpusbscsi);
return;
--- 425,431 ----
usb_urb_callback callback;
int res;
! DEBUG("Going through scatter/gather\n");
if (u->status < 0) {
handle_usb_error(hpusbscsi);
return;
***************
*** 548,557 ****
else
callback = simple_done;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
if (hpusbscsi->state != HP_STATE_PREMATURE)
hpusbscsi->state = HP_STATE_WORKING;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
FILL_BULK_URB(
u,
--- 436,445 ----
else
callback = simple_done;
! TRACE_STATE;
if (hpusbscsi->state != HP_STATE_PREMATURE)
hpusbscsi->state = HP_STATE_WORKING;
! TRACE_STATE;
FILL_BULK_URB(
u,
***************
*** 565,572 ****
res = usb_submit_urb(u);
if (res)
! handle_usb_error(hpusbscsi);
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
}
static void simple_done (struct urb *u)
--- 453,460 ----
res = usb_submit_urb(u);
if (res)
! hpusbscsi->state = HP_STATE_ERROR;
! TRACE_STATE;
}
static void simple_done (struct urb *u)
***************
*** 577,595 ****
handle_usb_error(hpusbscsi);
return;
}
! PDEBUG(1, "Data transfer done");
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
if (hpusbscsi->state != HP_STATE_PREMATURE) {
! if (u->status < 0) {
! handle_usb_error(hpusbscsi);
! } else {
! if (hpusbscsi->state != HP_STATE_ERROR) {
! hpusbscsi->state = HP_STATE_WAIT;
! } else {
! issue_request_sense(hpusbscsi);
! }
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
! }
} else {
if (hpusbscsi->scallback != NULL)
hpusbscsi->scallback(hpusbscsi->srb);
--- 465,478 ----
handle_usb_error(hpusbscsi);
return;
}
! DEBUG("Data transfer done\n");
! TRACE_STATE;
if (hpusbscsi->state != HP_STATE_PREMATURE) {
! if (u->status < 0)
! hpusbscsi->state = HP_STATE_ERROR;
! else
! hpusbscsi->state = HP_STATE_WAIT;
! TRACE_STATE;
} else {
if (hpusbscsi->scallback != NULL)
hpusbscsi->scallback(hpusbscsi->srb);
***************
*** 622,677 ****
handle_usb_error(hpusbscsi);
return;
}
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
if (hpusbscsi->state != HP_STATE_PREMATURE) {
hpusbscsi->state = HP_STATE_WORKING;
! PDEBUG(2, "state= %s", states[hpusbscsi->state]);
! }
! }
!
! static void request_sense_callback (struct urb *u)
! {
! struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
!
! if (u->status<0) {
! handle_usb_error(hpusbscsi);
! return;
! }
!
! FILL_BULK_URB(
! u,
! hpusbscsi->dev,
! hpusbscsi->current_data_pipe,
! hpusbscsi->srb->sense_buffer,
! SCSI_SENSE_BUFFERSIZE,
! simple_done,
! hpusbscsi
! );
!
! if (0 > usb_submit_urb(u)) {
! handle_usb_error(hpusbscsi);
! return;
! }
! if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR)
! hpusbscsi->state = HP_STATE_WORKING;
! }
!
! static void issue_request_sense (struct hpusbscsi *hpusbscsi)
! {
! FILL_BULK_URB(
! &hpusbscsi->dataurb,
! hpusbscsi->dev,
! usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out),
! &hpusbscsi->sense_command,
! SENSE_COMMAND_SIZE,
! request_sense_callback,
! hpusbscsi
! );
!
! hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
!
! if (0 > usb_submit_urb(&hpusbscsi->dataurb)) {
! handle_usb_error(hpusbscsi);
}
}
--- 505,519 ----
handle_usb_error(hpusbscsi);
return;
}
! TRACE_STATE;
if (hpusbscsi->state != HP_STATE_PREMATURE) {
hpusbscsi->state = HP_STATE_WORKING;
! TRACE_STATE;
! } else {
! if (hpusbscsi->scallback != NULL)
! hpusbscsi->scallback(hpusbscsi->srb);
! hpusbscsi->state = HP_STATE_FREE;
! TRACE_STATE;
}
}
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hpusbscsi.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hpusbscsi.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hpusbscsi.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hpusbscsi.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 4,17 ****
/* large parts based on or taken from code by John Fremlin and Matt Dharm */
/* this file is licensed under the GPL */
- /* A big thanks to Jose for untiring testing */
-
typedef void (*usb_urb_callback) (struct urb *);
typedef void (*scsi_callback)(Scsi_Cmnd *);
- #define SENSE_COMMAND_SIZE 6
- #define HPUSBSCSI_SENSE_LENGTH 0x16
-
struct hpusbscsi
{
struct list_head lh;
--- 4,12 ----
***************
*** 26,32 ****
int number;
scsi_callback scallback;
Scsi_Cmnd *srb;
- u8 sense_command[SENSE_COMMAND_SIZE];
int use_count;
wait_queue_head_t pending;
--- 21,26 ----
***************
*** 57,69 ****
static void simple_command_callback(struct urb *u);
static void scatter_gather_callback(struct urb *u);
static void simple_payload_callback (struct urb *u);
! static void control_interrupt_callback (struct urb *u);
! static void request_sense_callback (struct urb *u);
static void simple_done (struct urb *u);
static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
- static void issue_request_sense (struct hpusbscsi *hpusbscsi);
static Scsi_Host_Template hpusbscsi_scsi_host_template = {
name: "hpusbscsi",
--- 51,61 ----
static void simple_command_callback(struct urb *u);
static void scatter_gather_callback(struct urb *u);
static void simple_payload_callback (struct urb *u);
! static void control_interrupt_callback (struct urb *u);
static void simple_done (struct urb *u);
static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
static Scsi_Host_Template hpusbscsi_scsi_host_template = {
name: "hpusbscsi",
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hub.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hub.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hub.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hub.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 155,161 ****
static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint)
{
struct usb_device *dev = hub->dev;
! struct usb_hub_status *hubstatus;
char portstr[USB_MAXCHILDREN + 1];
unsigned int pipe;
int i, maxp, ret;
--- 155,161 ----
static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint)
{
struct usb_device *dev = hub->dev;
! struct usb_hub_status hubstatus;
char portstr[USB_MAXCHILDREN + 1];
unsigned int pipe;
int i, maxp, ret;
***************
*** 217,228 ****
break;
case 1:
dbg("Single TT");
- hub->tt.hub = dev;
break;
case 2:
! dbg("TT per port");
! hub->tt.hub = dev;
! hub->tt.multi = 1;
break;
default:
dbg("Unrecognized hub protocol %d",
--- 217,225 ----
break;
case 1:
dbg("Single TT");
break;
case 2:
! dbg("Multiple TT");
break;
default:
dbg("Unrecognized hub protocol %d",
***************
*** 258,286 ****
dbg("port removable status: %s", portstr);
! hubstatus = kmalloc(sizeof *hubstatus, GFP_KERNEL);
! if (!hubstatus) {
! err("Unable to allocate hubstatus");
! kfree(hub->descriptor);
! return -1;
! }
! ret = usb_get_hub_status(dev, hubstatus);
if (ret < 0) {
err("Unable to get hub status (err = %d)", ret);
- kfree(hubstatus);
kfree(hub->descriptor);
return -1;
}
! le16_to_cpus(&hubstatus->wHubStatus);
dbg("local power source is %s",
! (hubstatus->wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
dbg("%sover-current condition exists",
! (hubstatus->wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
!
! kfree(hubstatus);
/* Start the interrupt endpoint */
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
--- 255,274 ----
dbg("port removable status: %s", portstr);
! ret = usb_get_hub_status(dev, &hubstatus);
if (ret < 0) {
err("Unable to get hub status (err = %d)", ret);
kfree(hub->descriptor);
return -1;
}
! le16_to_cpus(&hubstatus.wHubStatus);
dbg("local power source is %s",
! (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
dbg("%sover-current condition exists",
! (hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
/* Start the interrupt endpoint */
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
***************
*** 296,306 ****
return -1;
}
! FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, hub,
! /* NOTE: in 2.5 fill_int_urb() converts the encoding */
! (dev->speed == USB_SPEED_HIGH)
! ? 1 << (endpoint->bInterval - 1)
! : endpoint->bInterval);
ret = usb_submit_urb(hub->urb);
if (ret) {
err("usb_submit_urb failed (%d)", ret);
--- 284,291 ----
return -1;
}
! FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
! hub, endpoint->bInterval);
ret = usb_submit_urb(hub->urb);
if (ret) {
err("usb_submit_urb failed (%d)", ret);
***************
*** 511,539 ****
err("cannot disconnect hub %d", dev->devnum);
}
- static int usb_hub_port_status(struct usb_device *hub, int port,
- u16 *status, u16 *change)
- {
- struct usb_port_status *portsts;
- int ret = -ENOMEM;
-
- portsts = kmalloc(sizeof(*portsts), GFP_KERNEL);
- if (portsts) {
- ret = usb_get_port_status(hub, port + 1, portsts);
- if (ret < 0)
- err("%s (%d) failed (err = %d)", __FUNCTION__, hub->devnum, ret);
- else {
- *status = le16_to_cpu(portsts->wPortStatus);
- *change = le16_to_cpu(portsts->wPortChange);
- dbg("port %d, portstatus %x, change %x, %s", port + 1,
- *status, *change, portspeed(*status));
- ret = 0;
- }
- kfree(portsts);
- }
- return ret;
- }
-
#define HUB_RESET_TRIES 5
#define HUB_PROBE_TRIES 2
#define HUB_SHORT_RESET_TIME 10
--- 496,501 ----
***************
*** 545,566 ****
struct usb_device *dev, unsigned int delay)
{
int delay_time, ret;
! u16 portstatus;
! u16 portchange;
for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay) {
/* wait to give the device a chance to reset */
wait_ms(delay);
/* read and decode port status */
! ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
if (ret < 0) {
return -1;
}
! /* Device went away? */
! if (!(portstatus & USB_PORT_STAT_CONNECTION))
! return 1;
/* bomb out completely if something weird happened */
if ((portchange & USB_PORT_STAT_C_CONNECTION))
--- 507,530 ----
struct usb_device *dev, unsigned int delay)
{
int delay_time, ret;
! struct usb_port_status portsts;
! unsigned short portchange, portstatus;
for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay) {
/* wait to give the device a chance to reset */
wait_ms(delay);
/* read and decode port status */
! ret = usb_get_port_status(hub, port + 1, &portsts);
if (ret < 0) {
+ err("get_port_status(%d) failed (err = %d)", port + 1, ret);
return -1;
}
! portstatus = le16_to_cpu(portsts.wPortStatus);
! portchange = le16_to_cpu(portsts.wPortChange);
! dbg("port %d, portstatus %x, change %x, %s", port + 1,
! portstatus, portchange, portspeed (portstatus));
/* bomb out completely if something weird happened */
if ((portchange & USB_PORT_STAT_C_CONNECTION))
***************
*** 628,684 ****
port + 1, hub->devnum, ret);
}
! /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
! *
! * Between connect detection and reset signaling there must be a delay
! * of 100ms at least for debounce and power-settling. The corresponding
! * timer shall restart whenever the downstream port detects a disconnect.
! *
! * Apparently there are some bluetooth and irda-dongles and a number
! * of low-speed devices which require longer delays of about 200-400ms.
! * Not covered by the spec - but easy to deal with.
! *
! * This implementation uses 400ms minimum debounce timeout and checks
! * every 100ms for transient disconnects to restart the delay.
! */
!
! #define HUB_DEBOUNCE_TIMEOUT 400
! #define HUB_DEBOUNCE_STEP 100
!
! /* return: -1 on error, 0 on success, 1 on disconnect. */
! static int usb_hub_port_debounce(struct usb_device *hub, int port)
{
- int ret;
- unsigned delay_time;
- u16 portchange, portstatus;
-
- for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) {
-
- /* wait debounce step increment */
- wait_ms(HUB_DEBOUNCE_STEP);
-
- ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
- if (ret < 0)
- return -1;
-
- if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
- usb_clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION);
- delay_time = 0;
- }
- else
- delay_time += HUB_DEBOUNCE_STEP;
- }
- return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
- }
-
- static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
- u16 portstatus, u16 portchange)
- {
- struct usb_device *hub = hubstate->dev;
struct usb_device *dev;
unsigned int delay = HUB_SHORT_RESET_TIME;
int i;
dbg("port %d, portstatus %x, change %x, %s",
port + 1, portstatus, portchange, portspeed (portstatus));
--- 592,608 ----
port + 1, hub->devnum, ret);
}
! static void usb_hub_port_connect_change(struct usb_device *hub, int port,
! struct usb_port_status *portsts)
{
struct usb_device *dev;
+ unsigned short portstatus, portchange;
unsigned int delay = HUB_SHORT_RESET_TIME;
int i;
+ char *portstr, *tempstr;
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);
dbg("port %d, portstatus %x, change %x, %s",
port + 1, portstatus, portchange, portspeed (portstatus));
***************
*** 697,713 ****
return;
}
! if (usb_hub_port_debounce(hub, port)) {
! err("connect-debounce failed, port %d disabled", port+1);
! usb_hub_port_disable(hub, port);
! return;
}
down(&usb_address0_sem);
for (i = 0; i < HUB_PROBE_TRIES; i++) {
! struct usb_device *pdev;
! int len;
/* Allocate a new device struct */
dev = usb_alloc_dev(hub, hub->bus);
--- 621,640 ----
return;
}
! /* Some low speed devices have problems with the quick delay, so */
! /* be a bit pessimistic with those devices. RHbug #23670 */
! if (portstatus & USB_PORT_STAT_LOW_SPEED) {
! wait_ms(400);
! delay = HUB_LONG_RESET_TIME;
}
down(&usb_address0_sem);
+ tempstr = kmalloc(1024, GFP_KERNEL);
+ portstr = kmalloc(1024, GFP_KERNEL);
+
for (i = 0; i < HUB_PROBE_TRIES; i++) {
! struct usb_device *pdev, *cdev;
/* Allocate a new device struct */
dev = usb_alloc_dev(hub, hub->bus);
***************
*** 727,764 ****
/* Find a new device ID for it */
usb_connect(dev);
! /* Set up TT records, if needed */
! if (hub->tt) {
! dev->tt = hub->tt;
! dev->ttport = hub->ttport;
! } else if (dev->speed != USB_SPEED_HIGH
! && hub->speed == USB_SPEED_HIGH) {
! dev->tt = &hubstate->tt;
! dev->ttport = port + 1;
! }
!
! /* Save readable and stable topology id, distinguishing
! * devices by location for diagnostics, tools, etc. The
! * string is a path along hub ports, from the root. Each
! * device's id will be stable until USB is re-cabled, and
! * hubs are often labeled with these port numbers.
! *
! * Initial size: ".NN" times five hubs + NUL = 16 bytes max
! * (quite rare, since most hubs have 4-6 ports).
! */
pdev = dev->parent;
! if (pdev->devpath [0] != '0') /* parent not root? */
! len = snprintf (dev->devpath, sizeof dev->devpath,
! "%s.%d", pdev->devpath, port + 1);
! /* root == "0", root port 2 == "2", port 3 that hub "2.3" */
! else
! len = snprintf (dev->devpath, sizeof dev->devpath,
! "%d", port + 1);
! if (len == sizeof dev->devpath)
! warn ("devpath size! usb/%03d/%03d path %s",
! dev->bus->busnum, dev->devnum, dev->devpath);
! info("new USB device %s-%s, assigned address %d",
! dev->bus->bus_name, dev->devpath, dev->devnum);
/* Run it through the hoops (find a driver, etc) */
if (!usb_new_device(dev))
--- 654,685 ----
/* Find a new device ID for it */
usb_connect(dev);
! /* Create a readable topology string */
! cdev = dev;
pdev = dev->parent;
! if (portstr && tempstr) {
! portstr[0] = 0;
! while (pdev) {
! int port;
!
! for (port = 0; port < pdev->maxchild; port++)
! if (pdev->children[port] == cdev)
! break;
!
! strcpy(tempstr, portstr);
! if (!strlen(tempstr))
! sprintf(portstr, "%d", port + 1);
! else
! sprintf(portstr, "%d/%s", port + 1, tempstr);
!
! cdev = pdev;
! pdev = pdev->parent;
! }
! info("USB new device connect on bus%d/%s, assigned device number %d",
! dev->bus->busnum, portstr, dev->devnum);
! } else
! info("USB new device connect on bus%d, assigned device number %d",
! dev->bus->busnum, dev->devnum);
/* Run it through the hoops (find a driver, etc) */
if (!usb_new_device(dev))
***************
*** 775,780 ****
--- 696,705 ----
usb_hub_port_disable(hub, port);
done:
up(&usb_address0_sem);
+ if (portstr)
+ kfree(portstr);
+ if (tempstr)
+ kfree(tempstr);
}
static void usb_hub_events(void)
***************
*** 783,793 ****
struct list_head *tmp;
struct usb_device *dev;
struct usb_hub *hub;
! struct usb_hub_status *hubsts;
! u16 hubstatus;
! u16 hubchange;
! u16 portstatus;
! u16 portchange;
int i, ret;
/*
--- 708,715 ----
struct list_head *tmp;
struct usb_device *dev;
struct usb_hub *hub;
! struct usb_hub_status hubsts;
! unsigned short hubstatus, hubchange;
int i, ret;
/*
***************
*** 829,843 ****
}
for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
! ret = usb_hub_port_status(dev, i, &portstatus, &portchange);
if (ret < 0) {
continue;
}
if (portchange & USB_PORT_STAT_C_CONNECTION) {
dbg("port %d connection change", i + 1);
! usb_hub_port_connect_change(hub, i, portstatus, portchange);
} else if (portchange & USB_PORT_STAT_C_ENABLE) {
dbg("port %d enable change, status %x", i + 1, portstatus);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
--- 751,772 ----
}
for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
! struct usb_port_status portsts;
! unsigned short portstatus, portchange;
!
! ret = usb_get_port_status(dev, i + 1, &portsts);
if (ret < 0) {
+ err("get_port_status failed (err = %d)", ret);
continue;
}
+ portstatus = le16_to_cpu(portsts.wPortStatus);
+ portchange = le16_to_cpu(portsts.wPortChange);
+
if (portchange & USB_PORT_STAT_C_CONNECTION) {
dbg("port %d connection change", i + 1);
! usb_hub_port_connect_change(dev, i, &portsts);
} else if (portchange & USB_PORT_STAT_C_ENABLE) {
dbg("port %d enable change, status %x", i + 1, portstatus);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
***************
*** 851,857 ****
(portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) {
err("already running port %i disabled by hub (EMI?), re-enabling...",
i + 1);
! usb_hub_port_connect_change(hub, i, portstatus, portchange);
}
}
--- 780,786 ----
(portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) {
err("already running port %i disabled by hub (EMI?), re-enabling...",
i + 1);
! usb_hub_port_connect_change(dev, i, &portsts);
}
}
***************
*** 873,899 ****
} /* end for i */
/* deal with hub status changes */
! hubsts = kmalloc(sizeof *hubsts, GFP_KERNEL);
! if (!hubsts) {
! err("couldn't allocate hubsts");
! } else {
! if (usb_get_hub_status(dev, hubsts) < 0)
! err("get_hub_status failed");
! else {
! hubstatus = le16_to_cpup(&hubsts->wHubStatus);
! hubchange = le16_to_cpup(&hubsts->wHubChange);
! if (hubchange & HUB_CHANGE_LOCAL_POWER) {
! dbg("hub power change");
! usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
! }
! if (hubchange & HUB_CHANGE_OVERCURRENT) {
! dbg("hub overcurrent change");
! wait_ms(500); /* Cool down */
! usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
! usb_hub_power_on(hub);
! }
}
- kfree(hubsts);
}
up(&hub->khubd_sem);
} /* end while (1) */
--- 802,822 ----
} /* end for i */
/* deal with hub status changes */
! if (usb_get_hub_status(dev, &hubsts) < 0)
! err("get_hub_status failed");
! else {
! hubstatus = le16_to_cpup(&hubsts.wHubStatus);
! hubchange = le16_to_cpup(&hubsts.wHubChange);
! if (hubchange & HUB_CHANGE_LOCAL_POWER) {
! dbg("hub power change");
! usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
! }
! if (hubchange & HUB_CHANGE_OVERCURRENT) {
! dbg("hub overcurrent change");
! wait_ms(500); /* Cool down */
! usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
! usb_hub_power_on(hub);
}
}
up(&hub->khubd_sem);
} /* end while (1) */
***************
*** 911,917 ****
*/
daemonize();
- reparent_to_init();
/* Setup a nice name */
strcpy(current->comm, "khubd");
--- 834,839 ----
***************
*** 919,925 ****
/* Send me a signal to get me die (for debugging) */
do {
usb_hub_events();
! wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
} while (!signal_pending(current));
dbg("usb_hub_thread exiting");
--- 841,847 ----
/* Send me a signal to get me die (for debugging) */
do {
usb_hub_events();
! interruptible_sleep_on(&khubd_wait);
} while (!signal_pending(current));
dbg("usb_hub_thread exiting");
***************
*** 1002,1008 ****
int usb_reset_device(struct usb_device *dev)
{
struct usb_device *parent = dev->parent;
! struct usb_device_descriptor *descriptor;
int i, ret, port = -1;
if (!parent) {
--- 924,930 ----
int usb_reset_device(struct usb_device *dev)
{
struct usb_device *parent = dev->parent;
! struct usb_device_descriptor descriptor;
int i, ret, port = -1;
if (!parent) {
***************
*** 1051,1072 ****
* If nothing changed, we reprogram the configuration and then
* the alternate settings.
*/
! descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
! if (!descriptor) {
! return -ENOMEM;
! }
! ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor,
! sizeof(*descriptor));
if (ret < 0)
return ret;
! le16_to_cpus(&descriptor->bcdUSB);
! le16_to_cpus(&descriptor->idVendor);
! le16_to_cpus(&descriptor->idProduct);
! le16_to_cpus(&descriptor->bcdDevice);
! if (memcmp(&dev->descriptor, descriptor, sizeof(*descriptor))) {
! kfree(descriptor);
usb_destroy_configuration(dev);
ret = usb_get_device_descriptor(dev);
--- 973,989 ----
* If nothing changed, we reprogram the configuration and then
* the alternate settings.
*/
! ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
! sizeof(descriptor));
if (ret < 0)
return ret;
! le16_to_cpus(&descriptor.bcdUSB);
! le16_to_cpus(&descriptor.idVendor);
! le16_to_cpus(&descriptor.idProduct);
! le16_to_cpus(&descriptor.bcdDevice);
! if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) {
usb_destroy_configuration(dev);
ret = usb_get_device_descriptor(dev);
***************
*** 1096,1103 ****
return 1;
}
- kfree(descriptor);
-
ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
if (ret < 0) {
err("failed to set active configuration (error=%d)", ret);
--- 1013,1018 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hub.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hub.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/hub.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/hub.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 2,8 ****
#define __LINUX_HUB_H
#include
- #include /* likely()/unlikely() */
/*
* Hub request types
--- 2,7 ----
***************
*** 137,143 ****
struct usb_hub_descriptor *descriptor;
struct semaphore khubd_sem;
- struct usb_tt tt; /* Transaction Translator */
};
#endif /* __LINUX_HUB_H */
--- 136,141 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/ibmcam.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/ibmcam.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/ibmcam.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/ibmcam.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,8 ****
/*
* USB IBM C-It Video Camera driver
*
! * Supports Xirlink C-It Video Camera, IBM PC Camera,
! * IBM NetCamera and Veo Stingray.
*
* This driver is based on earlier work of:
*
--- 1,7 ----
/*
* USB IBM C-It Video Camera driver
*
! * Supports IBM C-It Video Camera.
*
* This driver is based on earlier work of:
*
***************
*** 34,44 ****
#include "usbvideo.h"
! #define IBMCAM_VENDOR_ID 0x0545
! #define IBMCAM_PRODUCT_ID 0x8080
#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */
- #define VEO_800C_PRODUCT_ID 0x800C /* Veo Stingray, repackaged Model 2 */
- #define VEO_800D_PRODUCT_ID 0x800D /* Veo Stingray, repackaged Model 4 */
#define MAX_IBMCAM 4 /* How many devices we allow to connect */
#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */
--- 33,41 ----
#include "usbvideo.h"
! #define IBMCAM_VENDOR_ID 0x0545
! #define IBMCAM_PRODUCT_ID 0x8080
#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */
#define MAX_IBMCAM 4 /* How many devices we allow to connect */
#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */
***************
*** 3674,3681 ****
if (dev->descriptor.idVendor != IBMCAM_VENDOR_ID)
return NULL;
if ((dev->descriptor.idProduct != IBMCAM_PRODUCT_ID) &&
- (dev->descriptor.idProduct != VEO_800C_PRODUCT_ID) &&
- (dev->descriptor.idProduct != VEO_800D_PRODUCT_ID) &&
(dev->descriptor.idProduct != NETCAM_PRODUCT_ID))
return NULL;
--- 3671,3676 ----
***************
*** 3689,3696 ****
case 0x030A:
if (ifnum != 0)
return NULL;
! if ((dev->descriptor.idProduct == NETCAM_PRODUCT_ID) ||
! (dev->descriptor.idProduct == VEO_800D_PRODUCT_ID))
model = IBMCAM_MODEL_4;
else
model = IBMCAM_MODEL_2;
--- 3684,3690 ----
case 0x030A:
if (ifnum != 0)
return NULL;
! if (dev->descriptor.idProduct == NETCAM_PRODUCT_ID)
model = IBMCAM_MODEL_4;
else
model = IBMCAM_MODEL_2;
***************
*** 3705,3732 ****
dev->descriptor.bcdDevice);
return NULL;
}
!
! /* Print detailed info on what we found so far */
! do {
! char *brand = NULL;
! switch (dev->descriptor.idProduct) {
! case NETCAM_PRODUCT_ID:
! brand = "IBM NetCamera";
! break;
! case VEO_800C_PRODUCT_ID:
! brand = "Veo Stingray [800C]";
! break;
! case VEO_800D_PRODUCT_ID:
! brand = "Veo Stingray [800D]";
! break;
! case IBMCAM_PRODUCT_ID:
! default:
! brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
! break;
! }
! info("%s USB camera found (model %d, rev. 0x%04x)",
! brand, model, dev->descriptor.bcdDevice);
! } while (0);
/* Validate found interface: must have one ISO endpoint */
nas = dev->actconfig->interface[ifnum].num_altsetting;
--- 3699,3706 ----
dev->descriptor.bcdDevice);
return NULL;
}
! info("IBM USB camera found (model %d, rev. 0x%04x)",
! model, dev->descriptor.bcdDevice);
/* Validate found interface: must have one ISO endpoint */
nas = dev->actconfig->interface[ifnum].num_altsetting;
***************
*** 3934,3949 ****
usbvideo_Deregister(&cams);
}
static __devinitdata struct usb_device_id id_table[] = {
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */
- { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */
- { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
module_init(ibmcam_init);
module_exit(ibmcam_cleanup);
--- 3908,3925 ----
usbvideo_Deregister(&cams);
}
+ #if defined(usb_device_id_ver)
+
static __devinitdata struct usb_device_id id_table[] = {
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */
{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
+ #endif /* defined(usb_device_id_ver) */
+
module_init(ibmcam_init);
module_exit(ibmcam_cleanup);
LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb$B$@$1$KH/8+(B: ibmcam.h
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/inode.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/inode.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/inode.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/inode.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 628,634 ****
s->s_root = d_alloc_root(root_inode);
if (!s->s_root)
goto out_no_root;
- lock_kernel();
list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
for (i = 0; i < NRSPECIAL; i++) {
if (!(inode = iget(s, IROOT+1+i)))
--- 628,633 ----
***************
*** 647,653 ****
recurse_new_dev_inode(bus->root_hub, s);
}
up (&usb_bus_list_lock);
- unlock_kernel();
return s;
out_no_root:
--- 646,651 ----
***************
*** 656,668 ****
return NULL;
}
- /*
- * The usbdevfs name is now deprecated (as of 2.4.19).
- * It will be removed when the 2.7.x development cycle is started.
- * You have been warned :)
- */
static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);
- static DECLARE_FSTYPE(usbfs_type, "usbfs", usbdevfs_read_super, FS_SINGLE);
/* --------------------------------------------------------------------- */
--- 654,660 ----
***************
*** 759,769 ****
usb_deregister(&usbdevfs_driver);
return ret;
}
- if ((ret = register_filesystem(&usbfs_type))) {
- usb_deregister(&usbdevfs_driver);
- unregister_filesystem(&usbdevice_fs_type);
- return ret;
- }
#ifdef CONFIG_PROC_FS
/* create mount point for usbdevfs */
usbdir = proc_mkdir("usb", proc_bus);
--- 751,756 ----
***************
*** 775,781 ****
{
usb_deregister(&usbdevfs_driver);
unregister_filesystem(&usbdevice_fs_type);
- unregister_filesystem(&usbfs_type);
#ifdef CONFIG_PROC_FS
if (usbdir)
remove_proc_entry("usb", proc_bus);
--- 762,767 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/kaweth.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/kaweth.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/kaweth.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/kaweth.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 5,22 ****
* (c) 2000 Interlan Communications
* (c) 2000 Stephane Alnet
* (C) 2001 Brad Hards
- * (C) 2002 Oliver Neukum
*
* Original author: The Zapman
! * Inspired by, and much credit goes to Michael Rothwell
* for the test equipment, help, and patience
* Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
! * Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki
* for providing the firmware and driver resources.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
! * published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
--- 5,21 ----
* (c) 2000 Interlan Communications
* (c) 2000 Stephane Alnet
* (C) 2001 Brad Hards
*
* Original author: The Zapman
! * Inspired by, and much credit goes to Michael Rothwell
* for the test equipment, help, and patience
* Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
! * Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki
* for providing the firmware and driver resources.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
! * published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
***************
*** 26,32 ****
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
! * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
****************************************************************/
--- 25,31 ----
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
! * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
****************************************************************/
***************
*** 37,44 ****
* Fix bugs from previous two steps
* Snoop other OSs for any tricks we're not doing
* SMP locking
! * Reduce arbitrary timeouts
! * Smart multicast support
* Temporary MAC change support
* Tunable SOFs parameter - ioctl()?
* Ethernet stats collection
--- 36,43 ----
* Fix bugs from previous two steps
* Snoop other OSs for any tricks we're not doing
* SMP locking
! * Reduce arbitrary timeouts
! * Smart multicast support
* Temporary MAC change support
* Tunable SOFs parameter - ioctl()?
* Ethernet stats collection
***************
*** 55,64 ****
#include
#include
#include
- #include
- #include
#include
- #include
#define DEBUG
--- 54,60 ----
***************
*** 77,83 ****
#define KAWETH_MTU 1514
#define KAWETH_BUF_SIZE 1664
#define KAWETH_TX_TIMEOUT (5 * HZ)
- #define KAWETH_SCRATCH_SIZE 32
#define KAWETH_FIRMWARE_BUF_SIZE 4096
#define KAWETH_CONTROL_TIMEOUT (30 * HZ)
--- 73,78 ----
***************
*** 103,116 ****
#define KAWETH_SOFS_TO_WAIT 0x05
- #define INTBUFFERSIZE 4
! #define STATE_OFFSET 0
! #define STATE_MASK 0x40
! #define STATE_SHIFT 5
!
!
! MODULE_AUTHOR("Michael Zappe , Stephane Alnet , Brad Hards and Oliver Neukum ");
MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
MODULE_LICENSE("GPL");
--- 98,105 ----
#define KAWETH_SOFS_TO_WAIT 0x05
! MODULE_AUTHOR("Michael Zappe , Stephane Alnet and Brad Hards ");
MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
MODULE_LICENSE("GPL");
***************
*** 121,148 ****
);
static void kaweth_disconnect(struct usb_device *dev, void *ptr);
int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
! struct usb_ctrlrequest *cmd, void *data,
! int len, int timeout);
/****************************************************************
* usb_device_id
****************************************************************/
static struct usb_device_id usb_klsi_table[] = {
! { USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */
{ USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
! { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */
! { USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */
! { USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */
{ USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
! { USB_DEVICE(0x0565, 0x0003) }, /* Optus@Home UEP1045A */
! { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */
{ USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
{ USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
! { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */
! { USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */
! { USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */
! { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */
! { USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */
{ USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
{ USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
{ USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
--- 110,136 ----
);
static void kaweth_disconnect(struct usb_device *dev, void *ptr);
int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
! devrequest *cmd, void *data, int len,
! int timeout);
/****************************************************************
* usb_device_id
****************************************************************/
static struct usb_device_id usb_klsi_table[] = {
! { USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */
{ USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
! { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */
! { USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */
! { USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */
{ USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
! { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */
{ USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
{ USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
! { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */
! { USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */
! { USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */
! { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */
! { USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */
{ USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
{ USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
{ USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
***************
*** 154,163 ****
{ USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
{ USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
{ USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
! { USB_DEVICE(0x1485, 0x0001) }, /* Silicom U2E */
! { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
! { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
! { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
{ USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
{} /* Null terminator */
};
--- 142,150 ----
{ USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
{ USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
{ USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
! { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
! { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
! { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
{ USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
{} /* Null terminator */
};
***************
*** 168,177 ****
* kaweth_driver
****************************************************************/
static struct usb_driver kaweth_driver = {
! .name = "kaweth",
! .probe = kaweth_probe,
! .disconnect = kaweth_disconnect,
! .id_table = usb_klsi_table,
};
typedef __u8 eth_addr_t[6];
--- 155,164 ----
* kaweth_driver
****************************************************************/
static struct usb_driver kaweth_driver = {
! name: "kaweth",
! probe: kaweth_probe,
! disconnect: kaweth_disconnect,
! id_table: usb_klsi_table,
};
typedef __u8 eth_addr_t[6];
***************
*** 210,234 ****
spinlock_t device_lock;
__u32 status;
- int end;
- int removed;
- int suspend_lowmem;
- int linkstate;
struct usb_device *dev;
struct net_device *net;
! wait_queue_head_t term_wait;
struct urb *rx_urb;
struct urb *tx_urb;
- struct urb *irq_urb;
! struct sk_buff *tx_skb;
!
! __u8 *firmware_buf;
! __u8 scratch[KAWETH_SCRATCH_SIZE];
__u8 rx_buf[KAWETH_BUF_SIZE];
- __u8 intbuffer[INTBUFFERSIZE];
__u16 packet_filter_bitmap;
struct kaweth_ethernet_configuration configuration;
--- 197,213 ----
spinlock_t device_lock;
__u32 status;
struct usb_device *dev;
struct net_device *net;
! wait_queue_head_t control_wait;
struct urb *rx_urb;
struct urb *tx_urb;
! __u8 firmware_buf[KAWETH_FIRMWARE_BUF_SIZE];
! __u8 tx_buf[KAWETH_BUF_SIZE];
__u8 rx_buf[KAWETH_BUF_SIZE];
__u16 packet_filter_bitmap;
struct kaweth_ethernet_configuration configuration;
***************
*** 241,256 ****
* kaweth_control
****************************************************************/
static int kaweth_control(struct kaweth_device *kaweth,
! unsigned int pipe,
! __u8 request,
! __u8 requesttype,
! __u16 value,
__u16 index,
! void *data,
! __u16 size,
int timeout)
{
! struct usb_ctrlrequest *dr;
kaweth_dbg("kaweth_control()");
--- 220,235 ----
* kaweth_control
****************************************************************/
static int kaweth_control(struct kaweth_device *kaweth,
! unsigned int pipe,
! __u8 request,
! __u8 requesttype,
! __u16 value,
__u16 index,
! void *data,
! __u16 size,
int timeout)
{
! devrequest *dr;
kaweth_dbg("kaweth_control()");
***************
*** 259,276 ****
return -EBUSY;
}
! dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
! if (!dr) {
kaweth_dbg("kmalloc() failed");
return -ENOMEM;
}
!
! dr->bRequestType= requesttype;
! dr->bRequest = request;
! dr->wValue = cpu_to_le16p(&value);
! dr->wIndex = cpu_to_le16p(&index);
! dr->wLength = cpu_to_le16p(&size);
return kaweth_internal_control_msg(kaweth->dev,
pipe,
--- 238,257 ----
return -EBUSY;
}
! dr = kmalloc(sizeof(devrequest),
! in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
! if(!dr)
! {
kaweth_dbg("kmalloc() failed");
return -ENOMEM;
}
!
! dr->requesttype = requesttype;
! dr->request = request;
! dr->value = cpu_to_le16p(&value);
! dr->index = cpu_to_le16p(&index);
! dr->length = cpu_to_le16p(&size);
return kaweth_internal_control_msg(kaweth->dev,
pipe,
***************
*** 317,323 ****
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
urb_size,
0,
! (void *)&kaweth->scratch,
0,
KAWETH_CONTROL_TIMEOUT);
--- 298,304 ----
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
urb_size,
0,
! (void *)&kaweth->firmware_buf,
0,
KAWETH_CONTROL_TIMEOUT);
***************
*** 339,345 ****
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
sofs_wait,
0,
! (void *)&kaweth->scratch,
0,
KAWETH_CONTROL_TIMEOUT);
--- 320,326 ----
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
sofs_wait,
0,
! (void *)&kaweth->firmware_buf,
0,
KAWETH_CONTROL_TIMEOUT);
***************
*** 362,368 ****
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
receive_filter,
0,
! (void *)&kaweth->scratch,
0,
KAWETH_CONTROL_TIMEOUT);
--- 343,349 ----
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
receive_filter,
0,
! (void *)&kaweth->firmware_buf,
0,
KAWETH_CONTROL_TIMEOUT);
***************
*** 372,390 ****
/****************************************************************
* kaweth_download_firmware
****************************************************************/
! static int kaweth_download_firmware(struct kaweth_device *kaweth,
! __u8 *data,
__u16 data_len,
__u8 interrupt,
__u8 type)
! {
if(data_len > KAWETH_FIRMWARE_BUF_SIZE) {
kaweth_err("Firmware too big: %d", data_len);
return -ENOSPC;
}
!
memcpy(kaweth->firmware_buf, data, data_len);
!
kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
kaweth->firmware_buf[3] = data_len >> 8;
kaweth->firmware_buf[4] = type;
--- 353,371 ----
/****************************************************************
* kaweth_download_firmware
****************************************************************/
! static int kaweth_download_firmware(struct kaweth_device *kaweth,
! __u8 *data,
__u16 data_len,
__u8 interrupt,
__u8 type)
! {
if(data_len > KAWETH_FIRMWARE_BUF_SIZE) {
kaweth_err("Firmware too big: %d", data_len);
return -ENOSPC;
}
!
memcpy(kaweth->firmware_buf, data, data_len);
!
kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
kaweth->firmware_buf[3] = data_len >> 8;
kaweth->firmware_buf[4] = type;
***************
*** 393,400 ****
kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
kaweth->firmware_buf[2]);
! kaweth_dbg("Downloading firmware at %p to kaweth device at %p",
! data,
kaweth);
kaweth_dbg("Firmware length: %d", data_len);
--- 374,381 ----
kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
kaweth->firmware_buf[2]);
! kaweth_dbg("Downloading firmware at %p to kaweth device at %p",
! data,
kaweth);
kaweth_dbg("Firmware length: %d", data_len);
***************
*** 404,410 ****
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
0,
0,
! (void *)kaweth->firmware_buf,
data_len,
KAWETH_CONTROL_TIMEOUT);
}
--- 385,391 ----
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
0,
0,
! (void *)&kaweth->firmware_buf,
data_len,
KAWETH_CONTROL_TIMEOUT);
}
***************
*** 423,429 ****
kaweth->firmware_buf[5] = interrupt;
kaweth->firmware_buf[6] = 0x00;
kaweth->firmware_buf[7] = 0x00;
!
kaweth_dbg("Triggering firmware");
return kaweth_control(kaweth,
--- 404,410 ----
kaweth->firmware_buf[5] = interrupt;
kaweth->firmware_buf[6] = 0x00;
kaweth->firmware_buf[7] = 0x00;
!
kaweth_dbg("Triggering firmware");
return kaweth_control(kaweth,
***************
*** 432,438 ****
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
0,
0,
! (void *)kaweth->firmware_buf,
8,
KAWETH_CONTROL_TIMEOUT);
}
--- 413,419 ----
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
0,
0,
! (void *)&kaweth->firmware_buf,
8,
KAWETH_CONTROL_TIMEOUT);
}
***************
*** 447,458 ****
kaweth_dbg("kaweth_reset(%p)", kaweth);
result = kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
! USB_REQ_SET_CONFIGURATION,
! 0,
kaweth->dev->config[0].bConfigurationValue,
! 0,
! NULL,
! 0,
KAWETH_CONTROL_TIMEOUT);
udelay(10000);
--- 428,439 ----
kaweth_dbg("kaweth_reset(%p)", kaweth);
result = kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
! USB_REQ_SET_CONFIGURATION,
! 0,
kaweth->dev->config[0].bConfigurationValue,
! 0,
! NULL,
! 0,
KAWETH_CONTROL_TIMEOUT);
udelay(10000);
***************
*** 463,501 ****
}
static void kaweth_usb_receive(struct urb *);
- static void kaweth_resubmit_rx_urb(struct kaweth_device *);
-
- /****************************************************************
- int_callback
- *****************************************************************/
- static void int_callback(struct urb *u)
- {
- struct kaweth_device *kaweth = u->context;
- int act_state;
-
- /* we abuse the interrupt urb for rebsubmitting under low memory saving a timer */
- if (kaweth->suspend_lowmem)
- kaweth_resubmit_rx_urb(kaweth);
-
- /* we check the link state to report changes */
- if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) {
- if (!act_state)
- netif_carrier_on(kaweth->net);
- else
- netif_carrier_off(kaweth->net);
-
- kaweth->linkstate = act_state;
- }
-
- }
/****************************************************************
* kaweth_resubmit_rx_urb
****************************************************************/
! static void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth)
{
int result;
! long flags;
FILL_BULK_URB(kaweth->rx_urb,
kaweth->dev,
--- 444,458 ----
}
static void kaweth_usb_receive(struct urb *);
/****************************************************************
* kaweth_resubmit_rx_urb
****************************************************************/
! static inline void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth)
{
int result;
!
! memset(kaweth->rx_urb, 0, sizeof(*kaweth->rx_urb));
FILL_BULK_URB(kaweth->rx_urb,
kaweth->dev,
***************
*** 505,521 ****
kaweth_usb_receive,
kaweth);
! spin_lock_irqsave(&kaweth->device_lock, flags);
! if (!kaweth->removed) { /* no resubmit if disconnecting */
! if((result = usb_submit_urb(kaweth->rx_urb))) {
! if (result == -ENOMEM)
! kaweth->suspend_lowmem = 1;
! kaweth_err("resubmitting rx_urb %d failed", result);
! } else {
! kaweth->suspend_lowmem = 0;
! }
}
- spin_unlock_irqrestore(&kaweth->device_lock, flags);
}
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
--- 462,470 ----
kaweth_usb_receive,
kaweth);
! if((result = usb_submit_urb(kaweth->rx_urb))) {
! kaweth_err("resubmitting rx_urb %d failed", result);
}
}
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
***************
*** 527,556 ****
{
struct kaweth_device *kaweth = urb->context;
struct net_device *net = kaweth->net;
!
int count = urb->actual_length;
int count2 = urb->transfer_buffer_length;
!
__u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
struct sk_buff *skb;
! if(urb->status == -ECONNRESET || urb->status == -ECONNABORTED)
! /* we are killed - set a flag and wake the disconnect handler */
! {
! kaweth->end = 1;
! wake_up(&kaweth->term_wait);
return;
}
!
! if (kaweth->status & KAWETH_STATUS_CLOSING)
! return;
!
! if(urb->status && urb->status != -EREMOTEIO && count != 1) {
kaweth_err("%s RX status: %d count: %d packet_len: %d",
! net->name,
urb->status,
! count,
(int)pkt_len);
kaweth_resubmit_rx_urb(kaweth);
return;
--- 476,498 ----
{
struct kaweth_device *kaweth = urb->context;
struct net_device *net = kaweth->net;
!
int count = urb->actual_length;
int count2 = urb->transfer_buffer_length;
!
__u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
struct sk_buff *skb;
! if(kaweth->status & KAWETH_STATUS_CLOSING) {
return;
}
!
! if(urb->status && urb->status != -EREMOTEIO && count != 1) {
kaweth_err("%s RX status: %d count: %d packet_len: %d",
! net->name,
urb->status,
! count,
(int)pkt_len);
kaweth_resubmit_rx_urb(kaweth);
return;
***************
*** 564,587 ****
kaweth_resubmit_rx_urb(kaweth);
return;
}
!
if(!(skb = dev_alloc_skb(pkt_len+2))) {
kaweth_resubmit_rx_urb(kaweth);
return;
}
- skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
-
skb->dev = net;
eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
!
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, net);
!
netif_rx(skb);
!
kaweth->stats.rx_packets++;
kaweth->stats.rx_bytes += pkt_len;
}
--- 506,527 ----
kaweth_resubmit_rx_urb(kaweth);
return;
}
!
if(!(skb = dev_alloc_skb(pkt_len+2))) {
kaweth_resubmit_rx_urb(kaweth);
return;
}
skb->dev = net;
eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
!
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, net);
!
netif_rx(skb);
!
kaweth->stats.rx_packets++;
kaweth->stats.rx_bytes += pkt_len;
}
***************
*** 600,623 ****
kaweth_dbg("Opening network device.");
- MOD_INC_USE_COUNT;
-
kaweth_resubmit_rx_urb(kaweth);
- FILL_INT_URB(
- kaweth->irq_urb,
- kaweth->dev,
- usb_rcvintpipe(kaweth->dev, 3),
- kaweth->intbuffer,
- INTBUFFERSIZE,
- int_callback,
- kaweth,
- HZ/4);
-
- usb_submit_urb(kaweth->irq_urb);
-
netif_start_queue(net);
kaweth_async_set_rx_mode(kaweth);
return 0;
}
--- 540,551 ----
kaweth_dbg("Opening network device.");
kaweth_resubmit_rx_urb(kaweth);
netif_start_queue(net);
+ MOD_INC_USE_COUNT;
+
kaweth_async_set_rx_mode(kaweth);
return 0;
}
***************
*** 630,641 ****
struct kaweth_device *kaweth = net->priv;
netif_stop_queue(net);
!
! spin_lock_irq(&kaweth->device_lock);
kaweth->status |= KAWETH_STATUS_CLOSING;
- spin_unlock_irq(&kaweth->device_lock);
- usb_unlink_urb(kaweth->irq_urb);
usb_unlink_urb(kaweth->rx_urb);
kaweth->status &= ~KAWETH_STATUS_CLOSING;
--- 558,566 ----
struct kaweth_device *kaweth = net->priv;
netif_stop_queue(net);
!
kaweth->status |= KAWETH_STATUS_CLOSING;
usb_unlink_urb(kaweth->rx_urb);
kaweth->status &= ~KAWETH_STATUS_CLOSING;
***************
*** 647,681 ****
return 0;
}
- static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
- {
- u32 ethcmd;
-
- if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd)))
- return -EFAULT;
-
- switch (ethcmd) {
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
- strncpy(info.driver, "kaweth", sizeof(info.driver)-1);
- if (copy_to_user(useraddr, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- }
-
- return -EOPNOTSUPP;
- }
-
/****************************************************************
* kaweth_ioctl
****************************************************************/
static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
- switch (cmd) {
- case SIOCETHTOOL:
- return netdev_ethtool_ioctl(net, (void *) rq->ifr_data);
- }
return -EOPNOTSUPP;
}
--- 572,582 ----
***************
*** 685,697 ****
static void kaweth_usb_transmit_complete(struct urb *urb)
{
struct kaweth_device *kaweth = urb->context;
- struct sk_buff *skb = kaweth->tx_skb;
! if (urb->status != 0)
kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
netif_wake_queue(kaweth->net);
! dev_kfree_skb(skb);
}
/****************************************************************
--- 586,600 ----
static void kaweth_usb_transmit_complete(struct urb *urb)
{
struct kaweth_device *kaweth = urb->context;
! spin_lock(&kaweth->device_lock);
!
! if (urb->status)
kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
netif_wake_queue(kaweth->net);
!
! spin_unlock(&kaweth->device_lock);
}
/****************************************************************
***************
*** 700,765 ****
static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
! char *private_header;
!
int res;
spin_lock(&kaweth->device_lock);
- if (kaweth->removed) {
- /* our device is undergoing disconnection - we bail out */
- spin_unlock(&kaweth->device_lock);
- dev_kfree_skb(skb);
- return 0;
- }
-
kaweth_async_set_rx_mode(kaweth);
netif_stop_queue(net);
! /* We now decide whether we can put our special header into the sk_buff */
! if (skb_cloned(skb) || skb_headroom(skb) < 2) {
! /* no such luck - we make our own */
! struct sk_buff *copied_skb;
! copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC);
! dev_kfree_skb_any(skb);
! skb = copied_skb;
! if (!copied_skb) {
! kaweth->stats.tx_errors++;
! netif_start_queue(net);
! spin_unlock(&kaweth->device_lock);
! return 0;
! }
! }
! private_header = __skb_push(skb, 2);
! *private_header = cpu_to_le16(skb->len);
! kaweth->tx_skb = skb;
FILL_BULK_URB(kaweth->tx_urb,
kaweth->dev,
usb_sndbulkpipe(kaweth->dev, 2),
! private_header,
! skb->len,
kaweth_usb_transmit_complete,
kaweth);
- kaweth->end = 0;
- kaweth->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
if((res = usb_submit_urb(kaweth->tx_urb)))
{
kaweth_warn("kaweth failed tx_urb %d", res);
kaweth->stats.tx_errors++;
!
netif_start_queue(net);
! dev_kfree_skb(skb);
! }
! else
{
kaweth->stats.tx_packets++;
kaweth->stats.tx_bytes += skb->len;
net->trans_start = jiffies;
}
spin_unlock(&kaweth->device_lock);
return 0;
--- 603,647 ----
static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
! int count = skb->len;
!
int res;
spin_lock(&kaweth->device_lock);
kaweth_async_set_rx_mode(kaweth);
netif_stop_queue(net);
! *((__u16 *)kaweth->tx_buf) = cpu_to_le16(skb->len);
!
! memcpy(kaweth->tx_buf + 2, skb->data, skb->len);
! memset(kaweth->tx_urb, 0, sizeof(*kaweth->tx_urb));
FILL_BULK_URB(kaweth->tx_urb,
kaweth->dev,
usb_sndbulkpipe(kaweth->dev, 2),
! kaweth->tx_buf,
! count + 2,
kaweth_usb_transmit_complete,
kaweth);
if((res = usb_submit_urb(kaweth->tx_urb)))
{
kaweth_warn("kaweth failed tx_urb %d", res);
kaweth->stats.tx_errors++;
!
netif_start_queue(net);
! }
! else
{
kaweth->stats.tx_packets++;
kaweth->stats.tx_bytes += skb->len;
net->trans_start = jiffies;
}
+ dev_kfree_skb(skb);
+
spin_unlock(&kaweth->device_lock);
return 0;
***************
*** 771,777 ****
static void kaweth_set_rx_mode(struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
!
__u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
KAWETH_PACKET_FILTER_BROADCAST |
KAWETH_PACKET_FILTER_MULTICAST;
--- 653,659 ----
static void kaweth_set_rx_mode(struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
!
__u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
KAWETH_PACKET_FILTER_BROADCAST |
KAWETH_PACKET_FILTER_MULTICAST;
***************
*** 782,788 ****
if (net->flags & IFF_PROMISC) {
packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
! }
else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) {
packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST;
}
--- 664,670 ----
if (net->flags & IFF_PROMISC) {
packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
! }
else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) {
packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST;
}
***************
*** 797,803 ****
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
{
__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
! kaweth->packet_filter_bitmap = 0;
if(packet_filter_bitmap == 0) return;
{
--- 679,685 ----
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
{
__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
! kaweth->packet_filter_bitmap = 0;
if(packet_filter_bitmap == 0) return;
{
***************
*** 808,814 ****
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
packet_filter_bitmap,
0,
! (void *)&kaweth->scratch,
0,
KAWETH_CONTROL_TIMEOUT);
--- 690,696 ----
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
packet_filter_bitmap,
0,
! (void *)&kaweth->firmware_buf,
0,
KAWETH_CONTROL_TIMEOUT);
***************
*** 857,870 ****
int result = 0;
kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
! dev->devnum,
! (int)dev->descriptor.idVendor,
(int)dev->descriptor.idProduct,
(int)dev->descriptor.bcdDevice);
kaweth_dbg("Device at %p", dev);
! kaweth_dbg("Descriptor length: %x type: %x",
(int)dev->descriptor.bLength,
(int)dev->descriptor.bDescriptorType);
--- 739,752 ----
int result = 0;
kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
! dev->devnum,
! (int)dev->descriptor.idVendor,
(int)dev->descriptor.idProduct,
(int)dev->descriptor.bcdDevice);
kaweth_dbg("Device at %p", dev);
! kaweth_dbg("Descriptor length: %x type: %x",
(int)dev->descriptor.bLength,
(int)dev->descriptor.bDescriptorType);
***************
*** 876,884 ****
memset(kaweth, 0, sizeof(struct kaweth_device));
kaweth->dev = dev;
! spin_lock_init(&kaweth->device_lock);
! init_waitqueue_head(&kaweth->term_wait);
!
kaweth_dbg("Resetting.");
kaweth_reset(kaweth);
--- 758,767 ----
memset(kaweth, 0, sizeof(struct kaweth_device));
kaweth->dev = dev;
! kaweth->status = 0;
! kaweth->net = NULL;
! kaweth->device_lock = SPIN_LOCK_UNLOCKED;
!
kaweth_dbg("Resetting.");
kaweth_reset(kaweth);
***************
*** 893,917 ****
} else {
/* Download the firmware */
kaweth_info("Downloading firmware...");
! kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
! if ((result = kaweth_download_firmware(kaweth,
! kaweth_new_code,
! len_kaweth_new_code,
! 100,
2)) < 0) {
kaweth_err("Error downloading firmware (%d)", result);
- free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return NULL;
}
! if ((result = kaweth_download_firmware(kaweth,
! kaweth_new_code_fix,
! len_kaweth_new_code_fix,
! 100,
3)) < 0) {
kaweth_err("Error downloading firmware fix (%d)", result);
- free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return NULL;
}
--- 776,797 ----
} else {
/* Download the firmware */
kaweth_info("Downloading firmware...");
! if ((result = kaweth_download_firmware(kaweth,
! kaweth_new_code,
! len_kaweth_new_code,
! 100,
2)) < 0) {
kaweth_err("Error downloading firmware (%d)", result);
kfree(kaweth);
return NULL;
}
! if ((result = kaweth_download_firmware(kaweth,
! kaweth_new_code_fix,
! len_kaweth_new_code_fix,
! 100,
3)) < 0) {
kaweth_err("Error downloading firmware fix (%d)", result);
kfree(kaweth);
return NULL;
}
***************
*** 922,928 ****
126,
2)) < 0) {
kaweth_err("Error downloading trigger code (%d)", result);
- free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return NULL;
}
--- 802,807 ----
***************
*** 933,939 ****
126,
3)) < 0) {
kaweth_err("Error downloading trigger code fix (%d)", result);
- free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return NULL;
}
--- 812,817 ----
***************
*** 941,955 ****
if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
kaweth_err("Error triggering firmware (%d)", result);
- free_page((unsigned long)kaweth->firmware_buf);
kfree(kaweth);
return NULL;
}
/* Device will now disappear for a moment... */
kaweth_info("Firmware loaded. I'll be back...");
- free_page((unsigned long)kaweth->firmware_buf);
- kfree(kaweth);
return NULL;
}
--- 819,830 ----
***************
*** 973,979 ****
(int)kaweth->configuration.hw_addr[5]);
if(!memcmp(&kaweth->configuration.hw_addr,
! &bcast_addr,
sizeof(bcast_addr))) {
kaweth_err("Firmware not functioning properly, no net device created");
kfree(kaweth);
--- 848,854 ----
(int)kaweth->configuration.hw_addr[5]);
if(!memcmp(&kaweth->configuration.hw_addr,
! &bcast_addr,
sizeof(bcast_addr))) {
kaweth_err("Firmware not functioning properly, no net device created");
kfree(kaweth);
***************
*** 984,996 ****
kaweth_dbg("Error setting URB size");
return kaweth;
}
!
if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
kaweth_err("Error setting SOFS wait");
return kaweth;
}
! result = kaweth_set_receive_filter(kaweth,
KAWETH_PACKET_FILTER_DIRECTED |
KAWETH_PACKET_FILTER_BROADCAST |
KAWETH_PACKET_FILTER_MULTICAST);
--- 859,871 ----
kaweth_dbg("Error setting URB size");
return kaweth;
}
!
if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
kaweth_err("Error setting SOFS wait");
return kaweth;
}
! result = kaweth_set_receive_filter(kaweth,
KAWETH_PACKET_FILTER_DIRECTED |
KAWETH_PACKET_FILTER_BROADCAST |
KAWETH_PACKET_FILTER_MULTICAST);
***************
*** 999,1016 ****
kaweth_err("Error setting receive filter");
return kaweth;
}
!
kaweth_dbg("Initializing net device.");
kaweth->tx_urb = usb_alloc_urb(0);
- if (!kaweth->tx_urb)
- goto err_no_urb;
kaweth->rx_urb = usb_alloc_urb(0);
- if (!kaweth->rx_urb)
- goto err_only_tx;
- kaweth->irq_urb = usb_alloc_urb(0);
- if (!kaweth->irq_urb)
- goto err_tx_and_rx;
kaweth->net = init_etherdev(0, 0);
if (!kaweth->net) {
--- 874,884 ----
kaweth_err("Error setting receive filter");
return kaweth;
}
!
kaweth_dbg("Initializing net device.");
kaweth->tx_urb = usb_alloc_urb(0);
kaweth->rx_urb = usb_alloc_urb(0);
kaweth->net = init_etherdev(0, 0);
if (!kaweth->net) {
***************
*** 1019,1035 ****
}
memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
! memcpy(kaweth->net->dev_addr,
&kaweth->configuration.hw_addr,
sizeof(kaweth->configuration.hw_addr));
!
kaweth->net->priv = kaweth;
kaweth->net->open = kaweth_open;
kaweth->net->stop = kaweth_close;
kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
kaweth->net->tx_timeout = kaweth_tx_timeout;
!
kaweth->net->do_ioctl = kaweth_ioctl;
kaweth->net->hard_start_xmit = kaweth_start_xmit;
kaweth->net->set_multicast_list = kaweth_set_rx_mode;
--- 887,903 ----
}
memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
! memcpy(kaweth->net->dev_addr,
&kaweth->configuration.hw_addr,
sizeof(kaweth->configuration.hw_addr));
!
kaweth->net->priv = kaweth;
kaweth->net->open = kaweth_open;
kaweth->net->stop = kaweth_close;
kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
kaweth->net->tx_timeout = kaweth_tx_timeout;
!
kaweth->net->do_ioctl = kaweth_ioctl;
kaweth->net->hard_start_xmit = kaweth_start_xmit;
kaweth->net->set_multicast_list = kaweth_set_rx_mode;
***************
*** 1039,1056 ****
memset(&kaweth->stats, 0, sizeof(kaweth->stats));
kaweth_info("kaweth interface created at %s", kaweth->net->name);
!
kaweth_dbg("Kaweth probe returning.");
return kaweth;
-
- err_tx_and_rx:
- usb_free_urb(kaweth->rx_urb);
- err_only_tx:
- usb_free_urb(kaweth->tx_urb);
- err_no_urb:
- kfree(kaweth);
- return NULL;
}
/****************************************************************
--- 907,916 ----
memset(&kaweth->stats, 0, sizeof(kaweth->stats));
kaweth_info("kaweth interface created at %s", kaweth->net->name);
!
kaweth_dbg("Kaweth probe returning.");
return kaweth;
}
/****************************************************************
***************
*** 1067,1085 ****
return;
}
- kaweth->removed = 1;
- usb_unlink_urb(kaweth->irq_urb);
- usb_unlink_urb(kaweth->rx_urb);
-
- /* we need to wait for the urb to be cancelled, if it is active */
- spin_lock_irq(&kaweth->device_lock);
- if (usb_unlink_urb(kaweth->tx_urb) == -EINPROGRESS) {
- spin_unlock_irq(&kaweth->device_lock);
- wait_event(kaweth->term_wait, kaweth->end);
- } else {
- spin_unlock_irq(&kaweth->device_lock);
- }
-
if(kaweth->net) {
if(kaweth->net->flags & IFF_UP) {
kaweth_dbg("Closing net device");
--- 927,932 ----
***************
*** 1097,1115 ****
}
- // FIXME this completion stuff is a modified clone of
- // an OLD version of some stuff in usb.c ...
- struct kw_api_data {
- wait_queue_head_t wqh;
- int done;
- };
-
/*-------------------------------------------------------------------*
* completion handler for compatibility wrappers (sync control/bulk) *
*-------------------------------------------------------------------*/
! static void usb_api_blocking_completion(struct urb *urb)
{
! struct kw_api_data *awd = (struct kw_api_data *)urb->context;
awd->done=1;
wake_up(&awd->wqh);
--- 944,955 ----
}
/*-------------------------------------------------------------------*
* completion handler for compatibility wrappers (sync control/bulk) *
*-------------------------------------------------------------------*/
! static void usb_api_blocking_completion(urb_t *urb)
{
! struct usb_api_data *awd = (struct usb_api_data *)urb->context;
awd->done=1;
wake_up(&awd->wqh);
***************
*** 1120,1134 ****
*-------------------------------------------------------------------*/
// Starts urb and waits for completion or timeout
! static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
{
DECLARE_WAITQUEUE(wait, current);
! struct kw_api_data awd;
int status;
init_waitqueue_head(&awd.wqh);
awd.done = 0;
!
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&awd.wqh, &wait);
urb->context = &awd;
--- 960,974 ----
*-------------------------------------------------------------------*/
// Starts urb and waits for completion or timeout
! static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length)
{
DECLARE_WAITQUEUE(wait, current);
! struct usb_api_data awd;
int status;
init_waitqueue_head(&awd.wqh);
awd.done = 0;
!
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&awd.wqh, &wait);
urb->context = &awd;
***************
*** 1168,1177 ****
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
! struct usb_ctrlrequest *cmd, void *data, int len,
! int timeout)
{
! struct urb *urb;
int retv;
int length;
--- 1008,1016 ----
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
! devrequest *cmd, void *data, int len, int timeout)
{
! urb_t *urb;
int retv;
int length;
***************
*** 1219,1222 ****
-
--- 1058,1060 ----
LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb$B$@$1$KH/8+(B: m8xxhci.c
LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb$B$@$1$KH/8+(B: m8xxhci.h
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/mdc800.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/mdc800.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/mdc800.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/mdc800.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 30,43 ****
*
* The driver supports only one camera.
*
- * Fix: mdc800 used sleep_on and slept with io_lock held.
- * Converted sleep_on to waitqueues with schedule_timeout and made io_lock
- * a semaphore from a spinlock.
- * by Oliver Neukum <520047054719-0001@t-online.de>
- * (02/12/2001)
- *
- * Identify version on module load.
* (08/04/2001) gb
*
* version 0.7.5
* Fixed potential SMP races with Spinlocks.
--- 30,37 ----
*
* The driver supports only one camera.
*
* (08/04/2001) gb
+ * Identify version on module load.
*
* version 0.7.5
* Fixed potential SMP races with Spinlocks.
***************
*** 140,164 ****
unsigned int endpoint [4];
! struct urb * irq_urb;
wait_queue_head_t irq_wait;
- int irq_woken;
char* irq_urb_buffer;
int camera_busy; // is camera busy ?
int camera_request_ready; // Status to synchronize with irq
char camera_response [8]; // last Bytes send after busy
! struct urb * write_urb;
char* write_urb_buffer;
wait_queue_head_t write_wait;
- int written;
! struct urb * download_urb;
char* download_urb_buffer;
wait_queue_head_t download_wait;
- int downloaded;
int download_left; // Bytes left to download ?
--- 134,155 ----
unsigned int endpoint [4];
! purb_t irq_urb;
wait_queue_head_t irq_wait;
char* irq_urb_buffer;
int camera_busy; // is camera busy ?
int camera_request_ready; // Status to synchronize with irq
char camera_response [8]; // last Bytes send after busy
! purb_t write_urb;
char* write_urb_buffer;
wait_queue_head_t write_wait;
! purb_t download_urb;
char* download_urb_buffer;
wait_queue_head_t download_wait;
int download_left; // Bytes left to download ?
***************
*** 168,174 ****
int out_count; // Bytes in the buffer
int open; // Camera device open ?
! struct semaphore io_lock; // IO -lock
char in [8]; // Command Input Buffer
int in_count;
--- 159,165 ----
int out_count; // Bytes in the buffer
int open; // Camera device open ?
! spinlock_t io_lock; // IO -lock
char in [8]; // Command Input Buffer
int in_count;
***************
*** 293,299 ****
if (wake_up)
{
mdc800->camera_request_ready=0;
- mdc800->irq_woken=1;
wake_up_interruptible (&mdc800->irq_wait);
}
}
--- 284,289 ----
***************
*** 310,328 ****
*/
static int mdc800_usb_waitForIRQ (int mode, int msec)
{
- DECLARE_WAITQUEUE(wait, current);
-
mdc800->camera_request_ready=1+mode;
! add_wait_queue(&mdc800->irq_wait, &wait);
! set_current_state(TASK_INTERRUPTIBLE);
! if (!mdc800->irq_woken)
! {
! schedule_timeout (msec*HZ/1000);
! }
! remove_wait_queue(&mdc800->irq_wait, &wait);
! set_current_state(TASK_RUNNING);
! mdc800->irq_woken = 0;
if (mdc800->camera_request_ready>0)
{
--- 300,308 ----
*/
static int mdc800_usb_waitForIRQ (int mode, int msec)
{
mdc800->camera_request_ready=1+mode;
! interruptible_sleep_on_timeout (&mdc800->irq_wait, msec*HZ/1000);
if (mdc800->camera_request_ready>0)
{
***************
*** 357,363 ****
{
mdc800->state=READY;
}
- mdc800->written = 1;
wake_up_interruptible (&mdc800->write_wait);
}
--- 337,342 ----
***************
*** 385,391 ****
{
err ("request bytes fails (status:%i)", urb->status);
}
- mdc800->downloaded = 1;
wake_up_interruptible (&mdc800->download_wait);
}
--- 364,369 ----
***************
*** 467,473 ****
info ("Found Mustek MDC800 on USB.");
! down (&mdc800->io_lock);
mdc800->dev=dev;
mdc800->open=0;
--- 445,451 ----
info ("Found Mustek MDC800 on USB.");
! spin_lock (&mdc800->io_lock);
mdc800->dev=dev;
mdc800->open=0;
***************
*** 506,512 ****
mdc800->state=READY;
! up (&mdc800->io_lock);
return mdc800;
}
--- 484,490 ----
mdc800->state=READY;
! spin_unlock (&mdc800->io_lock);
return mdc800;
}
***************
*** 580,586 ****
int retval=0;
int errn=0;
! down (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
--- 558,564 ----
int retval=0;
int errn=0;
! spin_lock (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
***************
*** 616,622 ****
dbg ("Mustek MDC800 device opened.");
error_out:
! up (&mdc800->io_lock);
return errn;
}
--- 594,600 ----
dbg ("Mustek MDC800 device opened.");
error_out:
! spin_unlock (&mdc800->io_lock);
return errn;
}
***************
*** 629,637 ****
int retval=0;
dbg ("Mustek MDC800 device closed.");
! down (&mdc800->io_lock);
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
{
usb_unlink_urb (mdc800->irq_urb);
usb_unlink_urb (mdc800->write_urb);
usb_unlink_urb (mdc800->download_urb);
--- 607,616 ----
int retval=0;
dbg ("Mustek MDC800 device closed.");
! spin_lock (&mdc800->io_lock);
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
{
+ spin_unlock(&mdc800->io_lock);
usb_unlink_urb (mdc800->irq_urb);
usb_unlink_urb (mdc800->write_urb);
usb_unlink_urb (mdc800->download_urb);
***************
*** 639,648 ****
}
else
{
retval=-EIO;
}
! up(&mdc800->io_lock);
return retval;
}
--- 618,628 ----
}
else
{
+ spin_unlock (&mdc800->io_lock);
retval=-EIO;
}
!
return retval;
}
***************
*** 652,676 ****
*/
static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos)
{
! size_t left=len, sts=len; /* single transfer size */
char* ptr=buf;
- DECLARE_WAITQUEUE(wait, current);
! down (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
! up (&mdc800->io_lock);
return -EBUSY;
}
if (mdc800->state == WORKING)
{
warn ("Illegal State \"working\" reached during read ?!");
! up (&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open)
{
! up (&mdc800->io_lock);
return -EBUSY;
}
--- 632,655 ----
*/
static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos)
{
! int left=len, sts=len; /* single transfer size */
char* ptr=buf;
! spin_lock (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
! spin_unlock (&mdc800->io_lock);
return -EBUSY;
}
if (mdc800->state == WORKING)
{
warn ("Illegal State \"working\" reached during read ?!");
! spin_unlock (&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open)
{
! spin_unlock (&mdc800->io_lock);
return -EBUSY;
}
***************
*** 678,684 ****
{
if (signal_pending (current))
{
! up (&mdc800->io_lock);
return -EINTR;
}
--- 657,663 ----
{
if (signal_pending (current))
{
! spin_unlock (&mdc800->io_lock);
return -EINTR;
}
***************
*** 697,725 ****
if (usb_submit_urb (mdc800->download_urb))
{
err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
! up (&mdc800->io_lock);
return len-left;
}
! add_wait_queue(&mdc800->download_wait, &wait);
! set_current_state(TASK_INTERRUPTIBLE);
! if (!mdc800->downloaded)
! {
! schedule_timeout (TO_DOWNLOAD_GET_READY*HZ/1000);
! }
! set_current_state(TASK_RUNNING);
! remove_wait_queue(&mdc800->download_wait, &wait);
! mdc800->downloaded = 0;
if (mdc800->download_urb->status != 0)
{
err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
! up (&mdc800->io_lock);
return len-left;
}
}
else
{
/* No more bytes -> that's an error*/
! up (&mdc800->io_lock);
return -EIO;
}
}
--- 676,696 ----
if (usb_submit_urb (mdc800->download_urb))
{
err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
! spin_unlock (&mdc800->io_lock);
return len-left;
}
! interruptible_sleep_on_timeout (&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
if (mdc800->download_urb->status != 0)
{
err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
! spin_unlock (&mdc800->io_lock);
return len-left;
}
}
else
{
/* No more bytes -> that's an error*/
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
}
***************
*** 733,739 ****
}
}
! up (&mdc800->io_lock);
return len-left;
}
--- 704,710 ----
}
}
! spin_unlock (&mdc800->io_lock);
return len-left;
}
***************
*** 746,763 ****
*/
static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
{
! size_t i=0;
! DECLARE_WAITQUEUE(wait, current);
! down (&mdc800->io_lock);
if (mdc800->state != READY)
{
! up (&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open )
{
! up (&mdc800->io_lock);
return -EBUSY;
}
--- 717,733 ----
*/
static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
{
! int i=0;
! spin_lock (&mdc800->io_lock);
if (mdc800->state != READY)
{
! spin_unlock (&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open )
{
! spin_unlock (&mdc800->io_lock);
return -EBUSY;
}
***************
*** 765,771 ****
{
if (signal_pending (current))
{
! up (&mdc800->io_lock);
return -EINTR;
}
--- 735,741 ----
{
if (signal_pending (current))
{
! spin_unlock (&mdc800->io_lock);
return -EINTR;
}
***************
*** 787,793 ****
else
{
err ("Command is to long !\n");
! up (&mdc800->io_lock);
return -EIO;
}
--- 757,763 ----
else
{
err ("Command is to long !\n");
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
***************
*** 799,805 ****
if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
{
err ("Camera didn't get ready.\n");
! up (&mdc800->io_lock);
return -EIO;
}
--- 769,775 ----
if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
{
err ("Camera didn't get ready.\n");
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
***************
*** 811,832 ****
if (usb_submit_urb (mdc800->write_urb))
{
err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
! up (&mdc800->io_lock);
return -EIO;
}
! add_wait_queue(&mdc800->write_wait, &wait);
! set_current_state(TASK_INTERRUPTIBLE);
! if (!mdc800->written)
! {
! schedule_timeout (TO_WRITE_GET_READY*HZ/1000);
! }
! set_current_state(TASK_RUNNING);
! remove_wait_queue(&mdc800->write_wait, &wait);
! mdc800->written = 0;
if (mdc800->state == WORKING)
{
usb_unlink_urb (mdc800->write_urb);
! up (&mdc800->io_lock);
return -EIO;
}
--- 781,794 ----
if (usb_submit_urb (mdc800->write_urb))
{
err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
! interruptible_sleep_on_timeout (&mdc800->write_wait, TO_WRITE_GET_READY*HZ/1000);
if (mdc800->state == WORKING)
{
usb_unlink_urb (mdc800->write_urb);
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
***************
*** 838,844 ****
{
err ("call 0x07 before 0x05,0x3e");
mdc800->state=READY;
! up (&mdc800->io_lock);
return -EIO;
}
mdc800->pic_len=-1;
--- 800,806 ----
{
err ("call 0x07 before 0x05,0x3e");
mdc800->state=READY;
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
mdc800->pic_len=-1;
***************
*** 857,863 ****
if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
{
err ("requesting answer from irq fails");
! up (&mdc800->io_lock);
return -EIO;
}
--- 819,825 ----
if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
{
err ("requesting answer from irq fails");
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
***************
*** 885,891 ****
if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
{
err ("Command Timeout.");
! up (&mdc800->io_lock);
return -EIO;
}
}
--- 847,853 ----
if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
{
err ("Command Timeout.");
! spin_unlock (&mdc800->io_lock);
return -EIO;
}
}
***************
*** 895,901 ****
}
i++;
}
! up (&mdc800->io_lock);
return i;
}
--- 857,863 ----
}
i++;
}
! spin_unlock (&mdc800->io_lock);
return i;
}
***************
*** 954,969 ****
mdc800->dev=0;
mdc800->open=0;
mdc800->state=NOT_CONNECTED;
! init_MUTEX (&mdc800->io_lock);
init_waitqueue_head (&mdc800->irq_wait);
init_waitqueue_head (&mdc800->write_wait);
init_waitqueue_head (&mdc800->download_wait);
- mdc800->irq_woken = 0;
- mdc800->downloaded = 0;
- mdc800->written = 0;
-
try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
--- 916,927 ----
mdc800->dev=0;
mdc800->open=0;
mdc800->state=NOT_CONNECTED;
! spin_lock_init (&mdc800->io_lock);
init_waitqueue_head (&mdc800->irq_wait);
init_waitqueue_head (&mdc800->write_wait);
init_waitqueue_head (&mdc800->download_wait);
try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/microtek.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/microtek.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/microtek.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/microtek.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 117,124 ****
* 20010320 Version 0.4.3
* 20010408 Identify version on module load.
* 20011003 Fix multiple requests
- * 20020618 Version 0.4.4
- * 20020618 Confirm to utterly stupid rules about io_request_lock
*/
#include
--- 117,122 ----
***************
*** 146,152 ****
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.4.4"
#define DRIVER_AUTHOR "John Fremlin , Oliver Neukum "
#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
--- 144,150 ----
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.4.3"
#define DRIVER_AUTHOR "John Fremlin , Oliver Neukum "
#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
***************
*** 328,339 ****
} */
static inline void mts_urb_abort(struct mts_desc* desc) {
- spin_unlock_irq(&io_request_lock);
MTS_DEBUG_GOT_HERE();
mts_debug_dump(desc);
usb_unlink_urb( &desc->urb );
- spin_lock_irq(&io_request_lock);
}
static struct mts_desc * mts_list; /* list of active scanners */
--- 326,335 ----
***************
*** 418,431 ****
static int mts_scsi_host_reset (Scsi_Cmnd *srb)
{
-
struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
! spin_unlock_irq(&io_request_lock);
MTS_DEBUG_GOT_HERE();
mts_debug_dump(desc);
usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */
- spin_lock_irq(&io_request_lock);
return 0; /* RANT why here 0 and not SUCCESS */
}
--- 414,425 ----
static int mts_scsi_host_reset (Scsi_Cmnd *srb)
{
struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
!
MTS_DEBUG_GOT_HERE();
mts_debug_dump(desc);
usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */
return 0; /* RANT why here 0 and not SUCCESS */
}
***************
*** 441,447 ****
/* What a hideous hack! */
char local_name[48];
- spin_unlock_irq(&io_request_lock);
MTS_DEBUG_GOT_HERE();
--- 435,440 ----
***************
*** 452,458 ****
if (!sht->proc_name) {
MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
- spin_lock_irq(&io_request_lock);
return 0;
}
--- 445,450 ----
***************
*** 465,476 ****
if (desc->host == NULL) {
MTS_ERROR("Cannot register due to low memory");
kfree(sht->proc_name);
- spin_lock_irq(&io_request_lock);
return 0;
}
desc->host->hostdata[0] = (unsigned long)desc;
/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
! spin_lock_irq(&io_request_lock);
return 1;
}
--- 457,467 ----
if (desc->host == NULL) {
MTS_ERROR("Cannot register due to low memory");
kfree(sht->proc_name);
return 0;
}
desc->host->hostdata[0] = (unsigned long)desc;
/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
!
return 1;
}
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/ov511.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/ov511.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/ov511.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/ov511.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,17 ****
/*
* OmniVision OV511 Camera-to-USB Bridge Driver
*
! * Copyright (c) 1999-2002 Mark W. McClelland
! * Original decompression code Copyright 1998-2000 OmniVision Technologies
* Many improvements by Bret Wallach
* Color fixes by by Orion Sky Lawlor (2/26/2000)
* Snapshot code by Kevin Moore
* OV7620 fixes by Charl P. Botha
* Changes by Claudio Matsuoka
! * Original SAA7111A code by Dave Perks
! * URB error messages from pwc driver by Nemosoft
! * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox
! *
* Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt.
*
--- 1,13 ----
/*
* OmniVision OV511 Camera-to-USB Bridge Driver
*
! * Copyright (c) 1999-2000 Mark W. McClelland
* Many improvements by Bret Wallach
* Color fixes by by Orion Sky Lawlor (2/26/2000)
* Snapshot code by Kevin Moore
* OV7620 fixes by Charl P. Botha
* Changes by Claudio Matsuoka
! *
* Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt.
*
***************
*** 34,42 ****
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
- #include
#include
#include
#include
#include
--- 30,40 ----
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+ #define __NO_VERSION__
+
#include
#include
+ #include
#include
#include
#include
***************
*** 44,365 ****
#include
#include
#include
#include
#include
- #include
#include
- #if defined (__i386__)
- #include
- #endif
-
#include "ov511.h"
/*
* Version Information
*/
! #define DRIVER_VERSION "v1.61 for Linux 2.4"
! #define EMAIL "mark@alpha.dyndns.org"
! #define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \
! & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \
! & Claudio Matsuoka "
! #define DRIVER_DESC "ov511 USB Camera Driver"
#define OV511_I2C_RETRIES 3
- #define ENABLE_Y_QUANTABLE 1
- #define ENABLE_UV_QUANTABLE 1
! #define OV511_MAX_UNIT_VIDEO 16
! /* Pixel count * 3 bytes for RGB */
! #define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)
! #define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))
! /* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */
! #define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024)
! #define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
! /**********************************************************************
! * Module Parameters
! * (See ov511.txt for detailed descriptions of these)
! **********************************************************************/
! /* These variables (and all static globals) default to zero */
! static int autobright = 1;
! static int autogain = 1;
! static int autoexp = 1;
! static int debug;
! static int snapshot;
! static int fix_rgb_offset;
! static int force_rgb;
! static int cams = 1;
! static int compress;
! static int testpat;
! static int sensor_gbr;
! static int dumppix;
! static int led = 1;
! static int dump_bridge;
! static int dump_sensor;
! static int printph;
! static int phy = 0x1f;
! static int phuv = 0x05;
! static int pvy = 0x06;
! static int pvuv = 0x06;
! static int qhy = 0x14;
! static int qhuv = 0x03;
! static int qvy = 0x04;
! static int qvuv = 0x04;
! static int lightfreq;
! static int bandingfilter;
! static int clockdiv = -1;
! static int packetsize = -1;
! static int framedrop = -1;
! static int fastset;
! static int force_palette;
! static int backlight;
! static int unit_video[OV511_MAX_UNIT_VIDEO];
! static int remove_zeros;
! static int mirror;
!
! MODULE_PARM(autobright, "i");
! MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
! MODULE_PARM(autogain, "i");
! MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
! MODULE_PARM(autoexp, "i");
! MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
MODULE_PARM(debug, "i");
! MODULE_PARM_DESC(debug,
! "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
MODULE_PARM(snapshot, "i");
MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
! MODULE_PARM(fix_rgb_offset, "i");
! MODULE_PARM_DESC(fix_rgb_offset,
! "Fix vertical misalignment of red and blue at 640x480");
MODULE_PARM(force_rgb, "i");
MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
MODULE_PARM(cams, "i");
MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
MODULE_PARM(compress, "i");
! MODULE_PARM_DESC(compress, "Turn on compression (not reliable yet)");
MODULE_PARM(testpat, "i");
! MODULE_PARM_DESC(testpat,
! "Replace image with vertical bar testpattern (only partially working)");
MODULE_PARM(dumppix, "i");
! MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
! MODULE_PARM(led, "i");
! MODULE_PARM_DESC(led,
! "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
! MODULE_PARM(dump_bridge, "i");
! MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
! MODULE_PARM(dump_sensor, "i");
! MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
! MODULE_PARM(printph, "i");
! MODULE_PARM_DESC(printph, "Print frame start/end headers");
! MODULE_PARM(phy, "i");
! MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
! MODULE_PARM(phuv, "i");
! MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
! MODULE_PARM(pvy, "i");
! MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
! MODULE_PARM(pvuv, "i");
! MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
! MODULE_PARM(qhy, "i");
! MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
! MODULE_PARM(qhuv, "i");
! MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
! MODULE_PARM(qvy, "i");
! MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
! MODULE_PARM(qvuv, "i");
! MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
! MODULE_PARM(lightfreq, "i");
! MODULE_PARM_DESC(lightfreq,
! "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
! MODULE_PARM(bandingfilter, "i");
! MODULE_PARM_DESC(bandingfilter,
! "Enable banding filter (to reduce effects of fluorescent lighting)");
! MODULE_PARM(clockdiv, "i");
! MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
! MODULE_PARM(packetsize, "i");
! MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
! MODULE_PARM(framedrop, "i");
! MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
! MODULE_PARM(fastset, "i");
! MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
! MODULE_PARM(force_palette, "i");
! MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
! MODULE_PARM(backlight, "i");
! MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
! MODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i");
! MODULE_PARM_DESC(unit_video,
! "Force use of specific minor number(s). 0 is not allowed.");
! MODULE_PARM(remove_zeros, "i");
! MODULE_PARM_DESC(remove_zeros,
! "Remove zero-padding from uncompressed incoming data");
! MODULE_PARM(mirror, "i");
! MODULE_PARM_DESC(mirror, "Reverse image horizontally");
! MODULE_AUTHOR(DRIVER_AUTHOR);
! MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
- /**********************************************************************
- * Miscellaneous Globals
- **********************************************************************/
-
static struct usb_driver ov511_driver;
! static struct ov51x_decomp_ops *ov511_decomp_ops;
! static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;
! static struct ov51x_decomp_ops *ov518_decomp_ops;
! static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
!
! /* Number of times to retry a failed I2C transaction. Increase this if you
! * are getting "Failed to read sensor ID..." */
! static int i2c_detect_tries = 5;
!
! /* MMX support is present in kernel and CPU. Checked upon decomp module load. */
! static int ov51x_mmx_available;
!
! static __devinitdata struct usb_device_id device_table [] = {
! { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
! { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
! { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
! { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
! { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
! { } /* Terminating entry */
! };
!
! MODULE_DEVICE_TABLE (usb, device_table);
!
! static unsigned char yQuanTable511[] = OV511_YQUANTABLE;
! static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;
! static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
! static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
/**********************************************************************
! * Symbolic Names
**********************************************************************/
! /* Known OV511-based cameras */
! static struct symbolic_list camlist[] = {
! { 0, "Generic Camera (no ID)" },
! { 1, "Mustek WCam 3X" },
{ 3, "D-Link DSB-C300" },
! { 4, "Generic OV511/OV7610" },
{ 5, "Puretek PT-6007" },
- { 6, "Lifeview USB Life TV (NTSC)" },
{ 21, "Creative Labs WebCam 3" },
- { 22, "Lifeview USB Life TV (PAL D/K+B/G)" },
{ 36, "Koala-Cam" },
! { 38, "Lifeview USB Life TV (PAL)" },
! { 41, "Samsung Anycam MPC-M10" },
! { 43, "Mtekvision Zeca MV402" },
! { 46, "Suma eON" },
! { 70, "Lifeview USB Life TV (PAL/SECAM)" },
{ 100, "Lifeview RoboCam" },
{ 102, "AverMedia InterCam Elite" },
{ 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */
- { 192, "Webeye 2000B" },
{ -1, NULL }
};
! /* Video4Linux1 Palettes */
! static struct symbolic_list v4l1_plist[] = {
{ VIDEO_PALETTE_GREY, "GREY" },
! { VIDEO_PALETTE_HI240, "HI240" },
! { VIDEO_PALETTE_RGB565, "RGB565" },
{ VIDEO_PALETTE_RGB24, "RGB24" },
{ VIDEO_PALETTE_RGB32, "RGB32" },
! { VIDEO_PALETTE_RGB555, "RGB555" },
! { VIDEO_PALETTE_YUV422, "YUV422" },
! { VIDEO_PALETTE_YUYV, "YUYV" },
! { VIDEO_PALETTE_UYVY, "UYVY" },
! { VIDEO_PALETTE_YUV420, "YUV420" },
! { VIDEO_PALETTE_YUV411, "YUV411" },
! { VIDEO_PALETTE_RAW, "RAW" },
{ VIDEO_PALETTE_YUV422P,"YUV422P" },
{ VIDEO_PALETTE_YUV411P,"YUV411P" },
{ VIDEO_PALETTE_YUV420P,"YUV420P" },
{ VIDEO_PALETTE_YUV410P,"YUV410P" },
{ -1, NULL }
};
-
- static struct symbolic_list brglist[] = {
- { BRG_OV511, "OV511" },
- { BRG_OV511PLUS, "OV511+" },
- { BRG_OV518, "OV518" },
- { BRG_OV518PLUS, "OV518+" },
- { -1, NULL }
- };
-
- static struct symbolic_list senlist[] = {
- { SEN_OV76BE, "OV76BE" },
- { SEN_OV7610, "OV7610" },
- { SEN_OV7620, "OV7620" },
- { SEN_OV7620AE, "OV7620AE" },
- { SEN_OV6620, "OV6620" },
- { SEN_OV6630, "OV6630" },
- { SEN_OV6630AE, "OV6630AE" },
- { SEN_OV6630AF, "OV6630AF" },
- { SEN_OV8600, "OV8600" },
- { SEN_KS0127, "KS0127" },
- { SEN_KS0127B, "KS0127B" },
- { SEN_SAA7111A, "SAA7111A" },
- { -1, NULL }
- };
-
- /* URB error codes: */
- static struct symbolic_list urb_errlist[] = {
- { -ENOSR, "Buffer error (overrun)" },
- { -EPIPE, "Stalled (device not responding)" },
- { -EOVERFLOW, "Babble (bad cable?)" },
- { -EPROTO, "Bit-stuff error (bad cable?)" },
- { -EILSEQ, "CRC/Timeout" },
- { -ETIMEDOUT, "NAK (device does not respond)" },
- { -1, NULL }
- };
-
- /**********************************************************************
- * Prototypes
- **********************************************************************/
-
- static void ov51x_clear_snapshot(struct usb_ov511 *);
- static inline int sensor_get_picture(struct usb_ov511 *,
- struct video_picture *);
- #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
- static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
- static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
- static int ov51x_check_snapshot(struct usb_ov511 *);
#endif
/**********************************************************************
* Memory management
**********************************************************************/
/* Here we want the physical address of the memory.
! * This is used when initializing the contents of the area.
*/
! static inline unsigned long
! kvirt_to_pa(unsigned long adr)
{
! unsigned long kva, ret;
! kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
! kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva);
return ret;
}
! static void *
! rvmalloc(unsigned long size)
{
void *mem;
! unsigned long adr;
- size = PAGE_ALIGN(size);
mem = vmalloc_32(size);
if (!mem)
return NULL;
--- 42,280 ----
#include
#include
#include
+ #include
#include
#include
#include
#include "ov511.h"
/*
* Version Information
*/
! #define DRIVER_VERSION "v1.28"
! #define DRIVER_AUTHOR "Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka "
! #define DRIVER_DESC "OV511 USB Camera Driver"
#define OV511_I2C_RETRIES 3
! /* Video Size 640 x 480 x 3 bytes for RGB */
! #define MAX_FRAME_SIZE (640 * 480 * 3)
! #define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
!
! #define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384)
! /* PARAMETER VARIABLES: */
! static int autoadjust = 1; /* CCD dynamically changes exposure, etc... */
! static int video_nr = -1;
! /* 0=no debug messages
! * 1=init/detection/unload and other significant messages,
! * 2=some warning messages
! * 3=config/control function calls
! * 4=most function calls and data parsing messages
! * 5=highly repetitive mesgs
! * NOTE: This should be changed to 0, 1, or 2 for production kernels
! */
! static int debug = 0;
! /* Fix vertical misalignment of red and blue at 640x480 */
! static int fix_rgb_offset = 0;
! /* Snapshot mode enabled flag */
! static int snapshot = 0;
!
! /* Sensor detection override (global for all attached cameras) */
! static int sensor = 0;
!
! /* Increase this if you are getting "Failed to read sensor ID..." */
! static int i2c_detect_tries = 5;
!
! /* For legal values, see the OV7610/7620 specs under register Common F,
! * upper nybble (set to 0-F) */
! static int aperture = -1;
!
! /* Force image to be read in RGB instead of BGR. This option allow
! * programs that expect RGB data (e.g. gqcam) to work with this driver. */
! static int force_rgb = 0;
! /* Number of seconds before inactive buffers are deallocated */
! static int buf_timeout = 5;
!
! /* Number of cameras to stream from simultaneously */
! static int cams = 1;
!
! /* Prevent apps from timing out if frame is not done in time */
! static int retry_sync = 0;
!
! /* Enable compression. This is for experimentation only; compressed images
! * still cannot be decoded yet. */
! static int compress = 0;
!
! /* Display test pattern - doesn't work yet either */
! static int testpat = 0;
!
! /* Setting this to 1 will make the sensor output GBR422 instead on YUV420. Only
! * affects RGB24 mode. */
! static int sensor_gbr = 0;
!
! /* Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details. */
! static int dumppix = 0;
!
! MODULE_PARM(autoadjust, "i");
! MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure");
MODULE_PARM(debug, "i");
! MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");
! MODULE_PARM(fix_rgb_offset, "i");
! MODULE_PARM_DESC(fix_rgb_offset, "Fix vertical misalignment of red and blue at 640x480");
MODULE_PARM(snapshot, "i");
MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
! MODULE_PARM(sensor, "i");
! MODULE_PARM_DESC(sensor, "Override sensor detection");
! MODULE_PARM(i2c_detect_tries, "i");
! MODULE_PARM_DESC(i2c_detect_tries, "Number of tries to detect sensor");
! MODULE_PARM(aperture, "i");
! MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs");
MODULE_PARM(force_rgb, "i");
MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
+ MODULE_PARM(buf_timeout, "i");
+ MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");
MODULE_PARM(cams, "i");
MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
+ MODULE_PARM(retry_sync, "i");
+ MODULE_PARM_DESC(retry_sync, "Prevent apps from timing out");
MODULE_PARM(compress, "i");
! MODULE_PARM_DESC(compress, "Turn on compression (not functional yet)");
MODULE_PARM(testpat, "i");
! MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)");
! MODULE_PARM(sensor_gbr, "i");
! MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
MODULE_PARM(dumppix, "i");
! MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");
! MODULE_PARM(video_nr,"i");
! MODULE_AUTHOR( DRIVER_AUTHOR );
! MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
static struct usb_driver ov511_driver;
! /* I know, I know, global variables suck. This is only a temporary hack */
! int output_offset;
/**********************************************************************
! * List of known OV511-based cameras
**********************************************************************/
! static struct cam_list clist[] = {
! { 0, "generic model (no ID)" },
{ 3, "D-Link DSB-C300" },
! { 4, "generic OV511/OV7610" },
{ 5, "Puretek PT-6007" },
{ 21, "Creative Labs WebCam 3" },
{ 36, "Koala-Cam" },
! { 38, "Lifeview USB Life TV" }, /* No support yet! */
{ 100, "Lifeview RoboCam" },
{ 102, "AverMedia InterCam Elite" },
{ 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */
{ -1, NULL }
};
! static __devinitdata struct usb_device_id device_table [] = {
! { USB_DEVICE(0x05a9, 0x0511) }, /* OV511 */
! { USB_DEVICE(0x05a9, 0xA511) }, /* OV511+ */
! { USB_DEVICE(0x0813, 0x0002) }, /* Intel Play Me2Cam OV511+ */
! { } /* Terminating entry */
! };
!
! MODULE_DEVICE_TABLE (usb, device_table);
!
! #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
! static struct palette_list plist[] = {
{ VIDEO_PALETTE_GREY, "GREY" },
! { VIDEO_PALETTE_HI240, "HI240" },
! { VIDEO_PALETTE_RGB565, "RGB565" },
{ VIDEO_PALETTE_RGB24, "RGB24" },
{ VIDEO_PALETTE_RGB32, "RGB32" },
! { VIDEO_PALETTE_RGB555, "RGB555" },
! { VIDEO_PALETTE_YUV422, "YUV422" },
! { VIDEO_PALETTE_YUYV, "YUYV" },
! { VIDEO_PALETTE_UYVY, "UYVY" },
! { VIDEO_PALETTE_YUV420, "YUV420" },
! { VIDEO_PALETTE_YUV411, "YUV411" },
! { VIDEO_PALETTE_RAW, "RAW" },
{ VIDEO_PALETTE_YUV422P,"YUV422P" },
{ VIDEO_PALETTE_YUV411P,"YUV411P" },
{ VIDEO_PALETTE_YUV420P,"YUV420P" },
{ VIDEO_PALETTE_YUV410P,"YUV410P" },
{ -1, NULL }
};
#endif
/**********************************************************************
+ *
* Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the OV511 driver -claudio
**********************************************************************/
+ /* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+ {
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if (pte_present(pte)) {
+ ret = (unsigned long) page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+ }
+ }
+ }
+
+ return ret;
+ }
+
/* Here we want the physical address of the memory.
! * This is used when initializing the contents of the
! * area and marking the pages as reserved.
*/
! static inline unsigned long kvirt_to_pa(unsigned long adr)
{
! unsigned long va, kva, ret;
! va = VMALLOC_VMADDR(adr);
! kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = __pa(kva);
return ret;
}
! static void *rvmalloc(unsigned long size)
{
void *mem;
! unsigned long adr, page;
!
! /* Round it off to PAGE_SIZE */
! size += (PAGE_SIZE - 1);
! size &= ~(PAGE_SIZE - 1);
mem = vmalloc_32(size);
if (!mem)
return NULL;
***************
*** 367,393 ****
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem;
while (size > 0) {
! mem_map_reserve(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
! size -= PAGE_SIZE;
}
return mem;
}
! static void
! rvfree(void *mem, unsigned long size)
{
! unsigned long adr;
if (!mem)
return;
! adr = (unsigned long) mem;
! while ((long) size > 0) {
! mem_map_unreserve(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
! size -= PAGE_SIZE;
}
vfree(mem);
}
--- 282,318 ----
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem;
while (size > 0) {
! page = kvirt_to_pa(adr);
! mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE;
! if (size > PAGE_SIZE)
! size -= PAGE_SIZE;
! else
! size = 0;
}
return mem;
}
! static void rvfree(void *mem, unsigned long size)
{
! unsigned long adr, page;
if (!mem)
return;
! size += (PAGE_SIZE - 1);
! size &= ~(PAGE_SIZE - 1);
!
! adr=(unsigned long) mem;
! while (size > 0) {
! page = kvirt_to_pa(adr);
! mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE;
! if (size > PAGE_SIZE)
! size -= PAGE_SIZE;
! else
! size = 0;
}
vfree(mem);
}
***************
*** 402,475 ****
static struct proc_dir_entry *ov511_proc_entry = NULL;
extern struct proc_dir_entry *video_proc_entry;
- static struct file_operations ov511_control_fops = {
- ioctl: ov51x_control_ioctl,
- };
-
#define YES_NO(x) ((x) ? "yes" : "no")
! /* /proc/video/ov511//info */
! static int
! ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
! void *data)
{
char *out = page;
! int i, len;
! struct usb_ov511 *ov = data;
! struct video_picture p;
! unsigned char exp;
!
! if (!ov || !ov->dev)
! return -ENODEV;
!
! sensor_get_picture(ov, &p);
! sensor_get_exposure(ov, &exp);
/* IMPORTANT: This output MUST be kept under PAGE_SIZE
* or we need to get more sophisticated. */
! out += sprintf(out, "driver_version : %s\n", DRIVER_VERSION);
! out += sprintf(out, "custom_id : %d\n", ov->customid);
! out += sprintf(out, "model : %s\n", ov->desc);
! out += sprintf(out, "streaming : %s\n", YES_NO(ov->streaming));
! out += sprintf(out, "grabbing : %s\n", YES_NO(ov->grabbing));
! out += sprintf(out, "compress : %s\n", YES_NO(ov->compress));
! out += sprintf(out, "subcapture : %s\n", YES_NO(ov->sub_flag));
! out += sprintf(out, "sub_size : %d %d %d %d\n",
! ov->subx, ov->suby, ov->subw, ov->subh);
! out += sprintf(out, "data_format : %s\n",
! force_rgb ? "RGB" : "BGR");
! out += sprintf(out, "brightness : %d\n", p.brightness >> 8);
! out += sprintf(out, "colour : %d\n", p.colour >> 8);
! out += sprintf(out, "contrast : %d\n", p.contrast >> 8);
! out += sprintf(out, "hue : %d\n", p.hue >> 8);
! out += sprintf(out, "exposure : %d\n", exp);
! out += sprintf(out, "num_frames : %d\n", OV511_NUMFRAMES);
for (i = 0; i < OV511_NUMFRAMES; i++) {
! out += sprintf(out, "frame : %d\n", i);
! out += sprintf(out, " depth : %d\n",
! ov->frame[i].depth);
! out += sprintf(out, " size : %d %d\n",
! ov->frame[i].width, ov->frame[i].height);
! out += sprintf(out, " format : %s\n",
! symbolic(v4l1_plist, ov->frame[i].format));
! out += sprintf(out, " data_buffer : 0x%p\n",
! ov->frame[i].data);
! }
! out += sprintf(out, "snap_enabled : %s\n", YES_NO(ov->snap_enabled));
! out += sprintf(out, "bridge : %s\n",
! symbolic(brglist, ov->bridge));
! out += sprintf(out, "sensor : %s\n",
! symbolic(senlist, ov->sensor));
! out += sprintf(out, "packet_size : %d\n", ov->packet_size);
! out += sprintf(out, "framebuffer : 0x%p\n", ov->fbuf);
!
len = out - page;
len -= off;
if (len < count) {
*eof = 1;
! if (len <= 0)
! return 0;
} else
len = count;
--- 327,398 ----
static struct proc_dir_entry *ov511_proc_entry = NULL;
extern struct proc_dir_entry *video_proc_entry;
#define YES_NO(x) ((x) ? "yes" : "no")
! static int ov511_read_proc(char *page, char **start, off_t off,
! int count, int *eof, void *data)
{
char *out = page;
! int i, j, len;
! struct usb_ov511 *ov511 = data;
/* IMPORTANT: This output MUST be kept under PAGE_SIZE
* or we need to get more sophisticated. */
! out += sprintf (out, "driver_version : %s\n", DRIVER_VERSION);
! out += sprintf (out, "custom_id : %d\n", ov511->customid);
! out += sprintf (out, "model : %s\n", ov511->desc ?
! clist[ov511->desc].description : "unknown");
! out += sprintf (out, "streaming : %s\n", YES_NO (ov511->streaming));
! out += sprintf (out, "grabbing : %s\n", YES_NO (ov511->grabbing));
! out += sprintf (out, "compress : %s\n", YES_NO (ov511->compress));
! out += sprintf (out, "subcapture : %s\n", YES_NO (ov511->sub_flag));
! out += sprintf (out, "sub_size : %d %d %d %d\n",
! ov511->subx, ov511->suby, ov511->subw, ov511->subh);
! out += sprintf (out, "data_format : %s\n", force_rgb ? "RGB" : "BGR");
! out += sprintf (out, "brightness : %d\n", ov511->brightness >> 8);
! out += sprintf (out, "colour : %d\n", ov511->colour >> 8);
! out += sprintf (out, "contrast : %d\n", ov511->contrast >> 8);
! out += sprintf (out, "num_frames : %d\n", OV511_NUMFRAMES);
for (i = 0; i < OV511_NUMFRAMES; i++) {
! out += sprintf (out, "frame : %d\n", i);
! out += sprintf (out, " depth : %d\n",
! ov511->frame[i].depth);
! out += sprintf (out, " size : %d %d\n",
! ov511->frame[i].width, ov511->frame[i].height);
! out += sprintf (out, " format : ");
! for (j = 0; plist[j].num >= 0; j++) {
! if (plist[j].num == ov511->frame[i].format) {
! out += sprintf (out, "%s\n", plist[j].name);
! break;
! }
! }
! if (plist[j].num < 0)
! out += sprintf (out, "unknown\n");
! out += sprintf (out, " segsize : %d\n",
! ov511->frame[i].segsize);
! out += sprintf (out, " data_buffer : 0x%p\n",
! ov511->frame[i].data);
! }
! out += sprintf (out, "snap_enabled : %s\n", YES_NO (ov511->snap_enabled));
! out += sprintf (out, "bridge : %s\n",
! ov511->bridge == BRG_OV511 ? "OV511" :
! ov511->bridge == BRG_OV511PLUS ? "OV511+" :
! "unknown");
! out += sprintf (out, "sensor : %s\n",
! ov511->sensor == SEN_OV6620 ? "OV6620" :
! ov511->sensor == SEN_OV7610 ? "OV7610" :
! ov511->sensor == SEN_OV7620 ? "OV7620" :
! ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
! "unknown");
! out += sprintf (out, "packet_size : %d\n", ov511->packet_size);
! out += sprintf (out, "framebuffer : 0x%p\n", ov511->fbuf);
!
len = out - page;
len -= off;
if (len < count) {
*eof = 1;
! if (len <= 0) return 0;
} else
len = count;
***************
*** 478,639 ****
return len;
}
! /* /proc/video/ov511//button
! *
! * When the camera's button is pressed, the output of this will change from a
! * 0 to a 1 (ASCII). It will retain this value until it is read, after which
! * it will reset to zero.
! *
! * SECURITY NOTE: Since reading this file can change the state of the snapshot
! * status, it is important for applications that open it to keep it locked
! * against access by other processes, using flock() or a similar mechanism. No
! * locking is provided by this driver.
! */
! static int
! ov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,
! void *data)
{
! char *out = page;
! int len, status;
! struct usb_ov511 *ov = data;
!
! if (!ov || !ov->dev)
! return -ENODEV;
!
! status = ov51x_check_snapshot(ov);
! out += sprintf(out, "%d", status);
!
! if (status)
! ov51x_clear_snapshot(ov);
!
! len = out - page;
! len -= off;
! if (len < count) {
! *eof = 1;
! if (len <= 0)
! return 0;
! } else {
! len = count;
! }
!
! *start = page + off;
!
! return len;
}
! static void
! create_proc_ov511_cam(struct usb_ov511 *ov)
{
! char dirname[10];
!
! if (!ov511_proc_entry || !ov)
return;
! /* Create per-device directory */
! snprintf(dirname, 10, "%d", ov->vdev.minor);
! PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);
! ov->proc_devdir = create_proc_entry(dirname, S_IFDIR, ov511_proc_entry);
! if (!ov->proc_devdir)
! return;
! ov->proc_devdir->owner = THIS_MODULE;
! /* Create "info" entry (human readable device information) */
! PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);
! ov->proc_info = create_proc_read_entry("info", S_IFREG|S_IRUGO|S_IWUSR,
! ov->proc_devdir, ov511_read_proc_info, ov);
! if (!ov->proc_info)
return;
- ov->proc_info->owner = THIS_MODULE;
! /* Don't create it if old snapshot mode on (would cause race cond.) */
! if (!snapshot) {
! /* Create "button" entry (snapshot button status) */
! PDEBUG(4, "creating /proc/video/ov511/%s/button", dirname);
! ov->proc_button = create_proc_read_entry("button",
! S_IFREG|S_IRUGO|S_IWUSR, ov->proc_devdir,
! ov511_read_proc_button, ov);
! if (!ov->proc_button)
! return;
! }
! ov->proc_button->owner = THIS_MODULE;
!
! /* Create "control" entry (ioctl() interface) */
! PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);
! lock_kernel();
! ov->proc_control = create_proc_entry("control", S_IFREG|S_IRUGO|S_IWUSR,
! ov->proc_devdir);
! if (!ov->proc_control) {
! unlock_kernel();
! return;
! }
! ov->proc_control->owner = THIS_MODULE;
! ov->proc_control->data = ov;
! ov->proc_control->proc_fops = &ov511_control_fops;
! unlock_kernel();
}
! static void
! destroy_proc_ov511_cam(struct usb_ov511 *ov)
{
! char dirname[10];
!
! if (!ov || !ov->proc_devdir)
return;
!
! snprintf(dirname, 10, "%d", ov->vdev.minor);
!
! /* Destroy "control" entry */
! if (ov->proc_control) {
! PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);
! remove_proc_entry("control", ov->proc_devdir);
! ov->proc_control = NULL;
! }
!
! /* Destroy "button" entry */
! if (ov->proc_button) {
! PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);
! remove_proc_entry("button", ov->proc_devdir);
! ov->proc_button = NULL;
! }
!
! /* Destroy "info" entry */
! if (ov->proc_info) {
! PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);
! remove_proc_entry("info", ov->proc_devdir);
! ov->proc_info = NULL;
! }
!
! /* Destroy per-device directory */
! PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);
! remove_proc_entry(dirname, ov511_proc_entry);
! ov->proc_devdir = NULL;
}
! static void
! proc_ov511_create(void)
{
/* No current standard here. Alan prefers /proc/video/ as it keeps
* /proc "less cluttered than /proc/randomcardifoundintheshed/"
* -claudio
*/
if (video_proc_entry == NULL) {
! err("Error: /proc/video/ does not exist");
return;
}
! ov511_proc_entry = create_proc_entry("ov511", S_IFDIR,
! video_proc_entry);
if (ov511_proc_entry)
ov511_proc_entry->owner = THIS_MODULE;
else
! err("Unable to create /proc/video/ov511");
}
! static void
! proc_ov511_destroy(void)
{
! PDEBUG(3, "removing /proc/video/ov511");
if (ov511_proc_entry == NULL)
return;
--- 401,469 ----
return len;
}
! static int ov511_write_proc(struct file *file, const char *buffer,
! unsigned long count, void *data)
{
! return -EINVAL;
}
! static void create_proc_ov511_cam (struct usb_ov511 *ov511)
{
! char name[7];
! struct proc_dir_entry *ent;
!
! if (!ov511_proc_entry || !ov511)
return;
! sprintf(name, "video%d", ov511->vdev.minor);
! PDEBUG (4, "creating /proc/video/ov511/%s", name);
!
! ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry);
! if (!ent)
return;
! ent->data = ov511;
! ent->read_proc = ov511_read_proc;
! ent->write_proc = ov511_write_proc;
! ov511->proc_entry = ent;
}
! static void destroy_proc_ov511_cam (struct usb_ov511 *ov511)
{
! char name[7];
!
! if (!ov511 || !ov511->proc_entry)
return;
!
! sprintf(name, "video%d", ov511->vdev.minor);
! PDEBUG (4, "destroying %s", name);
! remove_proc_entry(name, ov511_proc_entry);
! ov511->proc_entry = NULL;
}
! static void proc_ov511_create(void)
{
/* No current standard here. Alan prefers /proc/video/ as it keeps
* /proc "less cluttered than /proc/randomcardifoundintheshed/"
* -claudio
*/
if (video_proc_entry == NULL) {
! err("Unable to initialise /proc/video/ov511");
return;
}
! ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry);
if (ov511_proc_entry)
ov511_proc_entry->owner = THIS_MODULE;
else
! err("Unable to initialise /proc/ov511");
}
! static void proc_ov511_destroy(void)
{
! PDEBUG (3, "removing /proc/video/ov511");
if (ov511_proc_entry == NULL)
return;
***************
*** 644,3053 ****
/**********************************************************************
*
! * Register I/O
*
**********************************************************************/
! /* Write an OV51x register */
! static int
! reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
{
int rc;
! PDEBUG(5, "0x%02X:0x%02X", reg, value);
! down(&ov->cbuf_lock);
! ov->cbuf[0] = value;
! rc = usb_control_msg(ov->dev,
! usb_sndctrlpipe(ov->dev, 0),
! (ov->bclass == BCL_OV518)?1:2 /* REG_IO */,
! USB_TYPE_VENDOR | USB_RECIP_DEVICE,
! 0, (__u16)reg, &ov->cbuf[0], 1, HZ);
! up(&ov->cbuf_lock);
if (rc < 0)
! err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));
return rc;
}
- /* Read from an OV51x register */
/* returns: negative is error, pos or zero is data */
! static int
! reg_r(struct usb_ov511 *ov, unsigned char reg)
{
int rc;
! down(&ov->cbuf_lock);
! rc = usb_control_msg(ov->dev,
! usb_rcvctrlpipe(ov->dev, 0),
! (ov->bclass == BCL_OV518)?1:3 /* REG_IO */,
! USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
! 0, (__u16)reg, &ov->cbuf[0], 1, HZ);
!
if (rc < 0) {
! err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));
} else {
! rc = ov->cbuf[0];
! PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
! }
!
! up(&ov->cbuf_lock);
!
! return rc;
! }
!
! /*
! * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
! * the same position as 1's in "mask" are cleared and set to "value". Bits
! * that are in the same position as 0's in "mask" are preserved, regardless
! * of their respective state in "value".
! */
! static int
! reg_w_mask(struct usb_ov511 *ov,
! unsigned char reg,
! unsigned char value,
! unsigned char mask)
! {
! int ret;
! unsigned char oldval, newval;
!
! ret = reg_r(ov, reg);
! if (ret < 0)
! return ret;
!
! oldval = (unsigned char) ret;
! oldval &= (~mask); /* Clear the masked bits */
! value &= mask; /* Enforce mask on value */
! newval = oldval | value; /* Set the desired bits */
!
! return (reg_w(ov, reg, newval));
! }
!
! /*
! * Writes multiple (n) byte value to a single register. Only valid with certain
! * registers (0x30 and 0xc4 - 0xce).
! */
! static int
! ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
! {
! int rc;
!
! PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);
!
! down(&ov->cbuf_lock);
!
! *((u32 *)ov->cbuf) = __cpu_to_le32(val);
!
! rc = usb_control_msg(ov->dev,
! usb_sndctrlpipe(ov->dev, 0),
! 1 /* REG_IO */,
! USB_TYPE_VENDOR | USB_RECIP_DEVICE,
! 0, (__u16)reg, ov->cbuf, n, HZ);
! up(&ov->cbuf_lock);
!
! if (rc < 0)
! err("reg write multiple: error %d: %s", rc,
! symbolic(urb_errlist, rc));
!
! return rc;
! }
!
! static int
! ov511_upload_quan_tables(struct usb_ov511 *ov)
! {
! unsigned char *pYTable = yQuanTable511;
! unsigned char *pUVTable = uvQuanTable511;
! unsigned char val0, val1;
! int i, rc, reg = R511_COMP_LUT_BEGIN;
!
! PDEBUG(4, "Uploading quantization tables");
!
! for (i = 0; i < OV511_QUANTABLESIZE / 2; i++) {
! if (ENABLE_Y_QUANTABLE) {
! val0 = *pYTable++;
! val1 = *pYTable++;
! val0 &= 0x0f;
! val1 &= 0x0f;
! val0 |= val1 << 4;
! rc = reg_w(ov, reg, val0);
! if (rc < 0)
! return rc;
! }
!
! if (ENABLE_UV_QUANTABLE) {
! val0 = *pUVTable++;
! val1 = *pUVTable++;
! val0 &= 0x0f;
! val1 &= 0x0f;
! val0 |= val1 << 4;
! rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0);
! if (rc < 0)
! return rc;
! }
!
! reg++;
! }
!
! return 0;
! }
!
! /* OV518 quantization tables are 8x4 (instead of 8x8) */
! static int
! ov518_upload_quan_tables(struct usb_ov511 *ov)
! {
! unsigned char *pYTable = yQuanTable518;
! unsigned char *pUVTable = uvQuanTable518;
! unsigned char val0, val1;
! int i, rc, reg = R511_COMP_LUT_BEGIN;
!
! PDEBUG(4, "Uploading quantization tables");
!
! for (i = 0; i < OV518_QUANTABLESIZE / 2; i++) {
! if (ENABLE_Y_QUANTABLE) {
! val0 = *pYTable++;
! val1 = *pYTable++;
! val0 &= 0x0f;
! val1 &= 0x0f;
! val0 |= val1 << 4;
! rc = reg_w(ov, reg, val0);
! if (rc < 0)
! return rc;
! }
!
! if (ENABLE_UV_QUANTABLE) {
! val0 = *pUVTable++;
! val1 = *pUVTable++;
! val0 &= 0x0f;
! val1 &= 0x0f;
! val0 |= val1 << 4;
! rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0);
! if (rc < 0)
! return rc;
! }
!
! reg++;
}
-
- return 0;
- }
-
- static int
- ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type)
- {
- int rc;
-
- /* Setting bit 0 not allowed on 518/518Plus */
- if (ov->bclass == BCL_OV518)
- reset_type &= 0xfe;
-
- PDEBUG(4, "Reset: type=0x%02X", reset_type);
-
- rc = reg_w(ov, R51x_SYS_RESET, reset_type);
- rc = reg_w(ov, R51x_SYS_RESET, 0);
-
- if (rc < 0)
- err("reset: command failed");
-
- return rc;
- }
-
- /**********************************************************************
- *
- * Low-level I2C I/O functions
- *
- **********************************************************************/
-
- /* NOTE: Do not call this function directly!
- * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from i2c_w(). Note that this function
- * always succeeds regardless of whether the sensor is present and working.
- */
- static int
- ov518_i2c_write_internal(struct usb_ov511 *ov,
- unsigned char reg,
- unsigned char value)
- {
- int rc;
-
- PDEBUG(5, "0x%02X:0x%02X", reg, value);
-
- /* Select camera register */
- rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
- if (rc < 0) return rc;
-
- /* Write "value" to I2C data port of OV511 */
- rc = reg_w(ov, R51x_I2C_DATA, value);
- if (rc < 0) return rc;
-
- /* Initiate 3-byte write cycle */
- rc = reg_w(ov, R518_I2C_CTL, 0x01);
- if (rc < 0) return rc;
-
- return 0;
}
! /* NOTE: Do not call this function directly! */
! static int
! ov511_i2c_write_internal(struct usb_ov511 *ov,
! unsigned char reg,
! unsigned char value)
{
int rc, retries;
! PDEBUG(5, "0x%02X:0x%02X", reg, value);
/* Three byte write cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
! rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
! if (rc < 0) return rc;
/* Write "value" to I2C data port of OV511 */
! rc = reg_w(ov, R51x_I2C_DATA, value);
! if (rc < 0) return rc;
/* Initiate 3-byte write cycle */
! rc = reg_w(ov, R511_I2C_CTL, 0x01);
! if (rc < 0) return rc;
! do rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
! if (rc < 0) return rc;
if ((rc&2) == 0) /* Ack? */
break;
#if 0
! /* I2C abort */
! reg_w(ov, R511_I2C_CTL, 0x10);
#endif
if (--retries < 0) {
err("i2c write retries exhausted");
! return -1;
}
}
return 0;
- }
-
- /* NOTE: Do not call this function directly!
- * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from i2c_r(). Note that this function
- * always succeeds regardless of whether the sensor is present and working.
- */
- static int
- ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
- {
- int rc, value;
-
- /* Select camera register */
- rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
- if (rc < 0) return rc;
-
- /* Initiate 2-byte write cycle */
- rc = reg_w(ov, R518_I2C_CTL, 0x03);
- if (rc < 0) return rc;
-
- /* Initiate 2-byte read cycle */
- rc = reg_w(ov, R518_I2C_CTL, 0x05);
- if (rc < 0) return rc;
! value = reg_r(ov, R51x_I2C_DATA);
!
! PDEBUG(5, "0x%02X:0x%02X", reg, value);
!
! return value;
}
! /* NOTE: Do not call this function directly!
! * returns: negative is error, pos or zero is data */
! static int
! ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
{
int rc, value, retries;
/* Two byte write cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
! rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
! if (rc < 0) return rc;
/* Initiate 2-byte write cycle */
! rc = reg_w(ov, R511_I2C_CTL, 0x03);
! if (rc < 0) return rc;
! do rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
! if (rc < 0) return rc;
if ((rc&2) == 0) /* Ack? */
break;
! /* I2C abort */
! reg_w(ov, R511_I2C_CTL, 0x10);
if (--retries < 0) {
err("i2c write retries exhausted");
! return -1;
}
}
/* Two byte read cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Initiate 2-byte read cycle */
! rc = reg_w(ov, R511_I2C_CTL, 0x05);
! if (rc < 0) return rc;
! do rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
! if (rc < 0) return rc;
if ((rc&2) == 0) /* Ack? */
break;
! /* I2C abort */
! rc = reg_w(ov, R511_I2C_CTL, 0x10);
! if (rc < 0) return rc;
if (--retries < 0) {
err("i2c read retries exhausted");
! return -1;
}
}
! value = reg_r(ov, R51x_I2C_DATA);
!
! PDEBUG(5, "0x%02X:0x%02X", reg, value);
! /* This is needed to make i2c_w() work */
! rc = reg_w(ov, R511_I2C_CTL, 0x05);
if (rc < 0)
! return rc;
!
return value;
}
! /* returns: negative is error, pos or zero is data */
! static int
! i2c_r(struct usb_ov511 *ov, unsigned char reg)
{
int rc;
! down(&ov->i2c_lock);
!
! if (ov->bclass == BCL_OV518)
! rc = ov518_i2c_read_internal(ov, reg);
! else
! rc = ov511_i2c_read_internal(ov, reg);
!
! up(&ov->i2c_lock);
return rc;
}
! static int
! i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
! {
! int rc;
!
! down(&ov->i2c_lock);
!
! if (ov->bclass == BCL_OV518)
! rc = ov518_i2c_write_internal(ov, reg, value);
! else
! rc = ov511_i2c_write_internal(ov, reg, value);
!
! up(&ov->i2c_lock);
!
! return rc;
! }
!
! /* Do not call this function directly! */
! static int
! ov51x_i2c_write_mask_internal(struct usb_ov511 *ov,
! unsigned char reg,
! unsigned char value,
! unsigned char mask)
! {
! int rc;
! unsigned char oldval, newval;
!
! if (mask == 0xff) {
! newval = value;
! } else {
! if (ov->bclass == BCL_OV518)
! rc = ov518_i2c_read_internal(ov, reg);
! else
! rc = ov511_i2c_read_internal(ov, reg);
! if (rc < 0)
! return rc;
!
! oldval = (unsigned char) rc;
! oldval &= (~mask); /* Clear the masked bits */
! value &= mask; /* Enforce mask on value */
! newval = oldval | value; /* Set the desired bits */
! }
!
! if (ov->bclass == BCL_OV518)
! return (ov518_i2c_write_internal(ov, reg, newval));
! else
! return (ov511_i2c_write_internal(ov, reg, newval));
! }
!
! /* Writes bits at positions specified by mask to an I2C reg. Bits that are in
! * the same position as 1's in "mask" are cleared and set to "value". Bits
! * that are in the same position as 0's in "mask" are preserved, regardless
! * of their respective state in "value".
! */
! static int
! i2c_w_mask(struct usb_ov511 *ov,
! unsigned char reg,
! unsigned char value,
! unsigned char mask)
! {
! int rc;
!
! down(&ov->i2c_lock);
! rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
! up(&ov->i2c_lock);
!
! return rc;
! }
!
! /* Set the read and write slave IDs. The "slave" argument is the write slave,
! * and the read slave will be set to (slave + 1). ov->i2c_lock should be held
! * when calling this. This should not be called from outside the i2c I/O
! * functions.
! */
! static inline int
! i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave)
! {
! int rc;
!
! rc = reg_w(ov, R51x_I2C_W_SID, slave);
! if (rc < 0) return rc;
!
! rc = reg_w(ov, R51x_I2C_R_SID, slave + 1);
! if (rc < 0) return rc;
!
! return 0;
! }
!
! #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
!
! /* Write to a specific I2C slave ID and register, using the specified mask */
! static int
! i2c_w_slave(struct usb_ov511 *ov,
! unsigned char slave,
! unsigned char reg,
! unsigned char value,
! unsigned char mask)
! {
! int rc = 0;
!
! down(&ov->i2c_lock);
!
! /* Set new slave IDs */
! rc = i2c_set_slave_internal(ov, slave);
! if (rc < 0) goto out;
!
! rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
!
! out:
! /* Restore primary IDs */
! if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)
! err("Couldn't restore primary I2C slave");
!
! up(&ov->i2c_lock);
! return rc;
! }
!
! /* Read from a specific I2C slave ID and register */
! static int
! i2c_r_slave(struct usb_ov511 *ov,
! unsigned char slave,
! unsigned char reg)
! {
! int rc;
!
! down(&ov->i2c_lock);
!
! /* Set new slave IDs */
! rc = i2c_set_slave_internal(ov, slave);
! if (rc < 0) goto out;
!
! if (ov->bclass == BCL_OV518)
! rc = ov518_i2c_read_internal(ov, reg);
! else
! rc = ov511_i2c_read_internal(ov, reg);
!
! out:
! /* Restore primary IDs */
! if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)
! err("Couldn't restore primary I2C slave");
!
! up(&ov->i2c_lock);
! return rc;
! }
!
! #endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) */
!
! /* Sets I2C read and write slave IDs. Returns <0 for error */
! static int
! ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid)
! {
! int rc;
!
! down(&ov->i2c_lock);
!
! rc = i2c_set_slave_internal(ov, sid);
! if (rc < 0) goto out;
!
! // FIXME: Is this actually necessary?
! rc = ov51x_reset(ov, OV511_RESET_NOREGS);
! if (rc < 0) goto out;
!
! out:
! up(&ov->i2c_lock);
! return rc;
! }
!
! static int
! write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals)
! {
! int rc;
!
! while (pRegvals->bus != OV511_DONE_BUS) {
! if (pRegvals->bus == OV511_REG_BUS) {
! if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0)
! return rc;
! } else if (pRegvals->bus == OV511_I2C_BUS) {
! if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)
! return rc;
! } else {
! err("Bad regval array");
! return -1;
! }
! pRegvals++;
! }
! return 0;
! }
!
! #ifdef OV511_DEBUG
! static void
! dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
{
int i;
int rc;
!
! for (i = reg1; i <= regn; i++) {
! rc = i2c_r(ov, i);
! info("Sensor[0x%02X] = 0x%02X", i, rc);
}
}
! static void
! dump_i2c_regs(struct usb_ov511 *ov)
{
! info("I2C REGS");
! dump_i2c_range(ov, 0x00, 0x7C);
}
! static void
! dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
{
int i;
int rc;
!
! for (i = reg1; i <= regn; i++) {
! rc = reg_r(ov, i);
! info("OV511[0x%02X] = 0x%02X", i, rc);
}
}
! /* FIXME: Should there be an OV518 version of this? */
! static void
! ov511_dump_regs(struct usb_ov511 *ov)
{
! info("CAMERA INTERFACE REGS");
! dump_reg_range(ov, 0x10, 0x1f);
! info("DRAM INTERFACE REGS");
! dump_reg_range(ov, 0x20, 0x23);
! info("ISO FIFO REGS");
! dump_reg_range(ov, 0x30, 0x31);
! info("PIO REGS");
! dump_reg_range(ov, 0x38, 0x39);
! dump_reg_range(ov, 0x3e, 0x3e);
! info("I2C REGS");
! dump_reg_range(ov, 0x40, 0x49);
! info("SYSTEM CONTROL REGS");
! dump_reg_range(ov, 0x50, 0x55);
! dump_reg_range(ov, 0x5e, 0x5f);
! info("OmniCE REGS");
! dump_reg_range(ov, 0x70, 0x79);
! /* NOTE: Quantization tables are not readable. You will get the value
! * in reg. 0x79 for every table register */
! dump_reg_range(ov, 0x80, 0x9f);
! dump_reg_range(ov, 0xa0, 0xbf);
}
#endif
-
- /*****************************************************************************/
-
- /* Temporarily stops OV511 from functioning. Must do this before changing
- * registers while the camera is streaming */
- static inline int
- ov51x_stop(struct usb_ov511 *ov)
- {
- PDEBUG(4, "stopping");
- ov->stopped = 1;
- if (ov->bclass == BCL_OV518)
- return (reg_w_mask(ov, R51x_SYS_RESET, 0x3a, 0x3a));
- else
- return (reg_w(ov, R51x_SYS_RESET, 0x3d));
- }
-
- /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
- * actually stopped (for performance). */
- static inline int
- ov51x_restart(struct usb_ov511 *ov)
- {
- if (ov->stopped) {
- PDEBUG(4, "restarting");
- ov->stopped = 0;
-
- /* Reinitialize the stream */
- if (ov->bclass == BCL_OV518)
- reg_w(ov, 0x2f, 0x80);
-
- return (reg_w(ov, R51x_SYS_RESET, 0x00));
- }
-
- return 0;
- }
-
- /* Resets the hardware snapshot button */
- static void
- ov51x_clear_snapshot(struct usb_ov511 *ov)
- {
- if (ov->bclass == BCL_OV511) {
- reg_w(ov, R51x_SYS_SNAP, 0x01);
- reg_w(ov, R51x_SYS_SNAP, 0x03);
- reg_w(ov, R51x_SYS_SNAP, 0x01);
- } else if (ov->bclass == BCL_OV518) {
- warn("snapshot reset not supported yet on OV518(+)");
- } else {
- err("clear snap: invalid bridge type");
- }
- }
-
- #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
- /* Checks the status of the snapshot button. Returns 1 if it was pressed since
- * it was last cleared, and zero in all other cases (including errors) */
- static int
- ov51x_check_snapshot(struct usb_ov511 *ov)
- {
- int ret, status = 0;
-
- if (ov->bclass == BCL_OV511) {
- ret = reg_r(ov, R51x_SYS_SNAP);
- if (ret < 0) {
- err("Error checking snspshot status (%d)", ret);
- } else if (ret & 0x08) {
- status = 1;
- }
- } else if (ov->bclass == BCL_OV518) {
- warn("snapshot check not supported yet on OV518(+)");
- } else {
- err("check snap: invalid bridge type");
- }
-
- return status;
- }
#endif
! /* This does an initial reset of an OmniVision sensor and ensures that I2C
! * is synchronized. Returns <0 for failure.
! */
! static int
! init_ov_sensor(struct usb_ov511 *ov)
! {
! int i, success;
!
! /* Reset the sensor */
! if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
!
! /* Wait for it to initialize */
! schedule_timeout (1 + 150 * HZ / 1000);
!
! for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
! if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
! (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
! success = 1;
! continue;
! }
!
! /* Reset the sensor */
! if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
! /* Wait for it to initialize */
! schedule_timeout(1 + 150 * HZ / 1000);
! /* Dummy read to sync I2C */
! if (i2c_r(ov, 0x00) < 0) return -EIO;
! }
!
! if (!success)
! return -EIO;
!
! PDEBUG(1, "I2C synced in %d attempt(s)", i);
!
! return 0;
! }
!
! static int
! ov511_set_packet_size(struct usb_ov511 *ov, int size)
! {
! int alt, mult;
!
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! mult = size >> 5;
!
! if (ov->bridge == BRG_OV511) {
! if (size == 0) alt = OV511_ALT_SIZE_0;
! else if (size == 257) alt = OV511_ALT_SIZE_257;
! else if (size == 513) alt = OV511_ALT_SIZE_513;
! else if (size == 769) alt = OV511_ALT_SIZE_769;
! else if (size == 993) alt = OV511_ALT_SIZE_993;
! else {
! err("Set packet size: invalid size (%d)", size);
! return -EINVAL;
! }
! } else if (ov->bridge == BRG_OV511PLUS) {
! if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
! else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
! else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
! else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;
! else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;
! else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;
! else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;
! else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;
! else {
! err("Set packet size: invalid size (%d)", size);
! return -EINVAL;
! }
! } else {
! err("Set packet size: Invalid bridge type");
! return -EINVAL;
! }
!
! PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt);
!
! if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0)
! return -EIO;
!
! if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
! err("Set packet size: set interface error");
! return -EBUSY;
! }
!
! if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
! return -EIO;
!
! ov->packet_size = size;
!
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! return 0;
! }
!
! /* Note: Unlike the OV511/OV511+, the size argument does NOT include the
! * optional packet number byte. The actual size *is* stored in ov->packet_size,
! * though. */
! static int
! ov518_set_packet_size(struct usb_ov511 *ov, int size)
! {
! int alt;
!
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! if (ov->bclass == BCL_OV518) {
! if (size == 0) alt = OV518_ALT_SIZE_0;
! else if (size == 128) alt = OV518_ALT_SIZE_128;
! else if (size == 256) alt = OV518_ALT_SIZE_256;
! else if (size == 384) alt = OV518_ALT_SIZE_384;
! else if (size == 512) alt = OV518_ALT_SIZE_512;
! else if (size == 640) alt = OV518_ALT_SIZE_640;
! else if (size == 768) alt = OV518_ALT_SIZE_768;
! else if (size == 896) alt = OV518_ALT_SIZE_896;
! else {
! err("Set packet size: invalid size (%d)", size);
! return -EINVAL;
! }
! } else {
! err("Set packet size: Invalid bridge type");
! return -EINVAL;
! }
!
! PDEBUG(3, "%d, alt=%d", size, alt);
!
! ov->packet_size = size;
! if (size > 0) {
! /* Program ISO FIFO size reg (packet number isn't included) */
! ov518_reg_w32(ov, 0x30, size, 2);
!
! if (ov->packet_numbering)
! ++ov->packet_size;
! }
!
! if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
! err("Set packet size: set interface error");
! return -EBUSY;
! }
!
! /* Initialize the stream */
! if (reg_w(ov, 0x2f, 0x80) < 0)
! return -EIO;
!
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
! return -EIO;
!
! return 0;
! }
!
! /* Upload compression params and quantization tables. Returns 0 for success. */
! static int
! ov511_init_compression(struct usb_ov511 *ov)
{
! int rc = 0;
!
! if (!ov->compress_inited) {
! reg_w(ov, 0x70, phy);
! reg_w(ov, 0x71, phuv);
! reg_w(ov, 0x72, pvy);
! reg_w(ov, 0x73, pvuv);
! reg_w(ov, 0x74, qhy);
! reg_w(ov, 0x75, qhuv);
! reg_w(ov, 0x76, qvy);
! reg_w(ov, 0x77, qvuv);
! if (ov511_upload_quan_tables(ov) < 0) {
! err("Error uploading quantization tables");
! rc = -EIO;
! goto out;
! }
! }
- ov->compress_inited = 1;
- out:
return rc;
}
! /* Upload compression params and quantization tables. Returns 0 for success. */
! static int
! ov518_init_compression(struct usb_ov511 *ov)
! {
! int rc = 0;
!
! if (!ov->compress_inited) {
! if (ov518_upload_quan_tables(ov) < 0) {
! err("Error uploading quantization tables");
! rc = -EIO;
! goto out;
! }
! }
!
! ov->compress_inited = 1;
! out:
! return rc;
! }
!
! /* -------------------------------------------------------------------------- */
!
! /* Sets sensor's contrast setting to "val" */
! static int
! sensor_set_contrast(struct usb_ov511 *ov, unsigned short val)
! {
! int rc;
!
! PDEBUG(3, "%d", val);
!
! if (ov->stop_during_set)
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV6620:
! {
! rc = i2c_w(ov, OV7610_REG_CNT, val >> 8);
! if (rc < 0)
! goto out;
! break;
! }
! case SEN_OV6630:
! {
! rc = i2c_w_mask(ov, OV7610_REG_CNT, val >> 12, 0x0f);
! if (rc < 0)
! goto out;
! break;
! }
! case SEN_OV7620:
! {
! unsigned char ctab[] = {
! 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
! 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
! };
!
! /* Use Y gamma control instead. Bit 0 enables it. */
! rc = i2c_w(ov, 0x64, ctab[val>>12]);
! if (rc < 0)
! goto out;
! break;
! }
! case SEN_SAA7111A:
! {
! rc = i2c_w(ov, 0x0b, val >> 9);
! if (rc < 0)
! goto out;
! break;
! }
! default:
! {
! PDEBUG(3, "Unsupported with this sensor");
! rc = -EPERM;
! goto out;
! }
! }
!
! rc = 0; /* Success */
! ov->contrast = val;
! out:
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! return rc;
! }
!
! /* Gets sensor's contrast setting */
! static int
! sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val)
! {
! int rc;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV6620:
! rc = i2c_r(ov, OV7610_REG_CNT);
! if (rc < 0)
! return rc;
! else
! *val = rc << 8;
! break;
! case SEN_OV6630:
! rc = i2c_r(ov, OV7610_REG_CNT);
! if (rc < 0)
! return rc;
! else
! *val = rc << 12;
! break;
! case SEN_OV7620:
! /* Use Y gamma reg instead. Bit 0 is the enable bit. */
! rc = i2c_r(ov, 0x64);
! if (rc < 0)
! return rc;
! else
! *val = (rc & 0xfe) << 8;
! break;
! case SEN_SAA7111A:
! *val = ov->contrast;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! return -EPERM;
! }
!
! PDEBUG(3, "%d", *val);
! ov->contrast = *val;
!
! return 0;
! }
!
! /* -------------------------------------------------------------------------- */
!
! /* Sets sensor's brightness setting to "val" */
! static int
! sensor_set_brightness(struct usb_ov511 *ov, unsigned short val)
! {
! int rc;
!
! PDEBUG(4, "%d", val);
!
! if (ov->stop_during_set)
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV76BE:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
! if (rc < 0)
! goto out;
! break;
! case SEN_OV7620:
! /* 7620 doesn't like manual changes when in auto mode */
! if (!ov->auto_brt) {
! rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
! if (rc < 0)
! goto out;
! }
! break;
! case SEN_SAA7111A:
! rc = i2c_w(ov, 0x0a, val >> 8);
! if (rc < 0)
! goto out;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! rc = -EPERM;
! goto out;
! }
!
! rc = 0; /* Success */
! ov->brightness = val;
! out:
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! return rc;
! }
!
! /* Gets sensor's brightness setting */
! static int
! sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val)
! {
! int rc;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV76BE:
! case SEN_OV7620:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = i2c_r(ov, OV7610_REG_BRT);
! if (rc < 0)
! return rc;
! else
! *val = rc << 8;
! break;
! case SEN_SAA7111A:
! *val = ov->brightness;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! return -EPERM;
! }
!
! PDEBUG(3, "%d", *val);
! ov->brightness = *val;
!
! return 0;
! }
!
! /* -------------------------------------------------------------------------- */
!
! /* Sets sensor's saturation (color intensity) setting to "val" */
! static int
! sensor_set_saturation(struct usb_ov511 *ov, unsigned short val)
! {
! int rc;
!
! PDEBUG(3, "%d", val);
!
! if (ov->stop_during_set)
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV76BE:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
! if (rc < 0)
! goto out;
! break;
! case SEN_OV7620:
! // /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
! // rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e);
! // if (rc < 0)
! // goto out;
! rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
! if (rc < 0)
! goto out;
! break;
! case SEN_SAA7111A:
! rc = i2c_w(ov, 0x0c, val >> 9);
! if (rc < 0)
! goto out;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! rc = -EPERM;
! goto out;
! }
!
! rc = 0; /* Success */
! ov->colour = val;
! out:
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! return rc;
! }
!
! /* Gets sensor's saturation (color intensity) setting */
! static int
! sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val)
! {
! int rc;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV76BE:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = i2c_r(ov, OV7610_REG_SAT);
! if (rc < 0)
! return rc;
! else
! *val = rc << 8;
! break;
! case SEN_OV7620:
! // /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */
! // rc = i2c_r(ov, 0x62);
! // if (rc < 0)
! // return rc;
! // else
! // *val = (rc & 0x7e) << 9;
! rc = i2c_r(ov, OV7610_REG_SAT);
! if (rc < 0)
! return rc;
! else
! *val = rc << 8;
! break;
! case SEN_SAA7111A:
! *val = ov->colour;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! return -EPERM;
! }
!
! PDEBUG(3, "%d", *val);
! ov->colour = *val;
!
! return 0;
! }
!
! /* -------------------------------------------------------------------------- */
!
! /* Sets sensor's hue (red/blue balance) setting to "val" */
! static int
! sensor_set_hue(struct usb_ov511 *ov, unsigned short val)
! {
! int rc;
!
! PDEBUG(3, "%d", val);
!
! if (ov->stop_during_set)
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8));
! if (rc < 0)
! goto out;
!
! rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8);
! if (rc < 0)
! goto out;
! break;
! case SEN_OV7620:
! // Hue control is causing problems. I will enable it once it's fixed.
! #if 0
! rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb);
! if (rc < 0)
! goto out;
!
! rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb);
! if (rc < 0)
! goto out;
! #endif
! break;
! case SEN_SAA7111A:
! rc = i2c_w(ov, 0x0d, (val + 32768) >> 8);
! if (rc < 0)
! goto out;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! rc = -EPERM;
! goto out;
! }
!
! rc = 0; /* Success */
! ov->hue = val;
! out:
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! return rc;
! }
!
! /* Gets sensor's hue (red/blue balance) setting */
! static int
! sensor_get_hue(struct usb_ov511 *ov, unsigned short *val)
! {
! int rc;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = i2c_r(ov, OV7610_REG_BLUE);
! if (rc < 0)
! return rc;
! else
! *val = rc << 8;
! break;
! case SEN_OV7620:
! rc = i2c_r(ov, 0x7a);
! if (rc < 0)
! return rc;
! else
! *val = rc << 8;
! break;
! case SEN_SAA7111A:
! *val = ov->hue;
! break;
! default:
! PDEBUG(3, "Unsupported with this sensor");
! return -EPERM;
! }
!
! PDEBUG(3, "%d", *val);
! ov->hue = *val;
!
! return 0;
! }
!
! /* -------------------------------------------------------------------------- */
!
! static inline int
! sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
! {
! int rc;
!
! PDEBUG(4, "sensor_set_picture");
!
! ov->whiteness = p->whiteness;
!
! /* Don't return error if a setting is unsupported, or rest of settings
! * will not be performed */
!
! rc = sensor_set_contrast(ov, p->contrast);
! if (FATAL_ERROR(rc))
! return rc;
!
! rc = sensor_set_brightness(ov, p->brightness);
! if (FATAL_ERROR(rc))
! return rc;
!
! rc = sensor_set_saturation(ov, p->colour);
! if (FATAL_ERROR(rc))
! return rc;
!
! rc = sensor_set_hue(ov, p->hue);
! if (FATAL_ERROR(rc))
! return rc;
!
! return 0;
! }
!
! static inline int
! sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
! {
! int rc;
!
! PDEBUG(4, "sensor_get_picture");
!
! /* Don't return error if a setting is unsupported, or rest of settings
! * will not be performed */
!
! rc = sensor_get_contrast(ov, &(p->contrast));
! if (FATAL_ERROR(rc))
! return rc;
!
! rc = sensor_get_brightness(ov, &(p->brightness));
! if (FATAL_ERROR(rc))
! return rc;
!
! rc = sensor_get_saturation(ov, &(p->colour));
! if (FATAL_ERROR(rc))
! return rc;
!
! rc = sensor_get_hue(ov, &(p->hue));
! if (FATAL_ERROR(rc))
! return rc;
!
! p->whiteness = 105 << 8;
!
! /* Can we get these from frame[0]? -claudio? */
! p->depth = ov->frame[0].depth;
! p->palette = ov->frame[0].format;
!
! return 0;
! }
!
! #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
! // FIXME: Exposure range is only 0x00-0x7f in interlace mode
! /* Sets current exposure for sensor. This only has an effect if auto-exposure
! * is off */
! static inline int
! sensor_set_exposure(struct usb_ov511 *ov, unsigned char val)
! {
! int rc;
!
! PDEBUG(3, "%d", val);
!
! if (ov->stop_during_set)
! if (ov51x_stop(ov) < 0)
! return -EIO;
!
! switch (ov->sensor) {
! case SEN_OV6620:
! case SEN_OV6630:
! case SEN_OV7610:
! case SEN_OV7620:
! case SEN_OV76BE:
! case SEN_OV8600:
! rc = i2c_w(ov, 0x10, val);
! if (rc < 0)
! goto out;
!
! break;
! case SEN_KS0127:
! case SEN_KS0127B:
! case SEN_SAA7111A:
! PDEBUG(3, "Unsupported with this sensor");
! return -EPERM;
! default:
! err("Sensor not supported for set_exposure");
! return -EINVAL;
! }
!
! rc = 0; /* Success */
! ov->exposure = val;
! out:
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! return rc;
! }
!
! /* Gets current exposure level from sensor, regardless of whether it is under
! * manual control. */
! static int
! sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val)
! {
! int rc;
!
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV6620:
! case SEN_OV6630:
! case SEN_OV7620:
! case SEN_OV76BE:
! case SEN_OV8600:
! rc = i2c_r(ov, 0x10);
! if (rc < 0)
! return rc;
! else
! *val = rc;
! break;
! case SEN_KS0127:
! case SEN_KS0127B:
! case SEN_SAA7111A:
! val = 0;
! PDEBUG(3, "Unsupported with this sensor");
! return -EPERM;
! default:
! err("Sensor not supported for get_exposure");
! return -EINVAL;
! }
!
! PDEBUG(3, "%d", *val);
! ov->exposure = *val;
!
! return 0;
! }
! #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
!
! /* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
! static inline void
! ov51x_led_control(struct usb_ov511 *ov, int enable)
! {
! PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
!
! if (ov->bridge == BRG_OV511PLUS)
! reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0);
! else if (ov->bclass == BCL_OV518)
! reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02);
!
! return;
! }
!
! /* Matches the sensor's internal frame rate to the lighting frequency.
! * Valid frequencies are:
! * 50 - 50Hz, for European and Asian lighting
! * 60 - 60Hz, for American lighting
! *
! * Tested with: OV7610, OV7620, OV76BE, OV6620
! * Unsupported: KS0127, KS0127B, SAA7111A
! * Returns: 0 for success
! */
! static int
! sensor_set_light_freq(struct usb_ov511 *ov, int freq)
! {
! int sixty;
!
! PDEBUG(4, "%d Hz", freq);
!
! if (freq == 60)
! sixty = 1;
! else if (freq == 50)
! sixty = 0;
! else {
! err("Invalid light freq (%d Hz)", freq);
! return -EINVAL;
! }
!
! switch (ov->sensor) {
! case SEN_OV7610:
! i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
! i2c_w(ov, 0x2b, sixty?0x00:0xac);
! i2c_w_mask(ov, 0x13, 0x10, 0x10);
! i2c_w_mask(ov, 0x13, 0x00, 0x10);
! break;
! case SEN_OV7620:
! case SEN_OV76BE:
! case SEN_OV8600:
! i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
! i2c_w(ov, 0x2b, sixty?0x00:0xac);
! i2c_w_mask(ov, 0x76, 0x01, 0x01);
! break;
! case SEN_OV6620:
! case SEN_OV6630:
! i2c_w(ov, 0x2b, sixty?0xa8:0x28);
! i2c_w(ov, 0x2a, sixty?0x84:0xa4);
! break;
! case SEN_KS0127:
! case SEN_KS0127B:
! case SEN_SAA7111A:
! PDEBUG(5, "Unsupported with this sensor");
! return -EPERM;
! default:
! err("Sensor not supported for set_light_freq");
! return -EINVAL;
! }
!
! ov->lightfreq = freq;
!
! return 0;
! }
!
! /* If enable is true, turn on the sensor's banding filter, otherwise turn it
! * off. This filter tries to reduce the pattern of horizontal light/dark bands
! * caused by some (usually fluorescent) lighting. The light frequency must be
! * set either before or after enabling it with ov51x_set_light_freq().
! *
! * Tested with: OV7610, OV7620, OV76BE, OV6620.
! * Unsupported: KS0127, KS0127B, SAA7111A
! * Returns: 0 for success
! */
! static inline int
! sensor_set_banding_filter(struct usb_ov511 *ov, int enable)
! {
! int rc;
!
! PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
!
! if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
! || ov->sensor == SEN_SAA7111A) {
! PDEBUG(5, "Unsupported with this sensor");
! return -EPERM;
! }
!
! rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04);
! if (rc < 0)
! return rc;
!
! ov->bandfilt = enable;
!
! return 0;
! }
!
! /* If enable is true, turn on the sensor's auto brightness control, otherwise
! * turn it off.
! *
! * Unsupported: KS0127, KS0127B, SAA7111A
! * Returns: 0 for success
! */
! static inline int
! sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)
! {
! int rc;
!
! PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
!
! if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
! || ov->sensor == SEN_SAA7111A) {
! PDEBUG(5, "Unsupported with this sensor");
! return -EPERM;
! }
!
! rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10);
! if (rc < 0)
! return rc;
!
! ov->auto_brt = enable;
!
! return 0;
! }
!
! /* If enable is true, turn on the sensor's auto exposure control, otherwise
! * turn it off.
! *
! * Unsupported: KS0127, KS0127B, SAA7111A
! * Returns: 0 for success
! */
! static inline int
! sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)
! {
! PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
!
! switch (ov->sensor) {
! case SEN_OV7610:
! i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80);
! break;
! case SEN_OV6620:
! case SEN_OV7620:
! case SEN_OV76BE:
! case SEN_OV8600:
! i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01);
! break;
! case SEN_OV6630:
! i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10);
! break;
! case SEN_KS0127:
! case SEN_KS0127B:
! case SEN_SAA7111A:
! PDEBUG(5, "Unsupported with this sensor");
! return -EPERM;
! default:
! err("Sensor not supported for set_auto_exposure");
! return -EINVAL;
! }
!
! ov->auto_exp = enable;
!
! return 0;
! }
!
! /* Modifies the sensor's exposure algorithm to allow proper exposure of objects
! * that are illuminated from behind.
! *
! * Tested with: OV6620, OV7620
! * Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A
! * Returns: 0 for success
! */
! static int
! sensor_set_backlight(struct usb_ov511 *ov, int enable)
! {
! PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
!
! switch (ov->sensor) {
! case SEN_OV7620:
! case SEN_OV8600:
! i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0);
! i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
! i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
! break;
! case SEN_OV6620:
! i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0);
! i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
! i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80);
! break;
! case SEN_OV6630:
! i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0);
! i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
! i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
! break;
! case SEN_OV7610:
! case SEN_OV76BE:
! case SEN_KS0127:
! case SEN_KS0127B:
! case SEN_SAA7111A:
! PDEBUG(5, "Unsupported with this sensor");
! return -EPERM;
! default:
! err("Sensor not supported for set_backlight");
! return -EINVAL;
! }
!
! ov->backlight = enable;
!
! return 0;
! }
!
! static inline int
! sensor_set_mirror(struct usb_ov511 *ov, int enable)
! {
! PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
!
! switch (ov->sensor) {
! case SEN_OV6620:
! case SEN_OV6630:
! case SEN_OV7610:
! case SEN_OV7620:
! case SEN_OV76BE:
! case SEN_OV8600:
! i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40);
! break;
! case SEN_KS0127:
! case SEN_KS0127B:
! case SEN_SAA7111A:
! PDEBUG(5, "Unsupported with this sensor");
! return -EPERM;
! default:
! err("Sensor not supported for set_mirror");
! return -EINVAL;
! }
!
! ov->mirror = enable;
!
! return 0;
! }
!
! /* Returns number of bits per pixel (regardless of where they are located;
! * planar or not), or zero for unsupported format.
! */
! static inline int
! get_depth(int palette)
! {
! switch (palette) {
! case VIDEO_PALETTE_GREY: return 8;
! case VIDEO_PALETTE_YUV420: return 12;
! case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
! case VIDEO_PALETTE_RGB565: return 16;
! case VIDEO_PALETTE_RGB24: return 24;
! case VIDEO_PALETTE_YUV422: return 16;
! case VIDEO_PALETTE_YUYV: return 16;
! case VIDEO_PALETTE_YUV422P: return 16; /* Planar */
! default: return 0; /* Invalid format */
! }
! }
!
! /* Bytes per frame. Used by read(). Return of 0 indicates error */
! static inline long int
! get_frame_length(struct ov511_frame *frame)
! {
! if (!frame)
! return 0;
! else
! return ((frame->width * frame->height
! * get_depth(frame->format)) >> 3);
! }
!
! static int
! mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
! int mode, int sub_flag, int qvga)
! {
! int clock;
!
! /******** Mode (VGA/QVGA) and sensor specific regs ********/
!
! switch (ov->sensor) {
! case SEN_OV7610:
! i2c_w(ov, 0x14, qvga?0x24:0x04);
! // FIXME: Does this improve the image quality or frame rate?
! #if 0
! i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
! i2c_w(ov, 0x24, 0x10);
! i2c_w(ov, 0x25, qvga?0x40:0x8a);
! i2c_w(ov, 0x2f, qvga?0x30:0xb0);
! i2c_w(ov, 0x35, qvga?0x1c:0x9c);
! #endif
! break;
! case SEN_OV7620:
! // i2c_w(ov, 0x2b, 0x00);
! i2c_w(ov, 0x14, qvga?0xa4:0x84);
! i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
! i2c_w(ov, 0x24, qvga?0x20:0x3a);
! i2c_w(ov, 0x25, qvga?0x30:0x60);
! i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
! i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0);
! i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
! break;
! case SEN_OV76BE:
! // i2c_w(ov, 0x2b, 0x00);
! i2c_w(ov, 0x14, qvga?0xa4:0x84);
! // FIXME: Enable this once 7620AE uses 7620 initial settings
! #if 0
! i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
! i2c_w(ov, 0x24, qvga?0x20:0x3a);
! i2c_w(ov, 0x25, qvga?0x30:0x60);
! i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
! i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0);
! i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
! #endif
! break;
! case SEN_OV6620:
! case SEN_OV6630:
! i2c_w(ov, 0x14, qvga?0x24:0x04);
! /* No special settings yet */
! break;
! default:
! err("Invalid sensor");
! return -EINVAL;
! }
!
! /******** Palette-specific regs ********/
!
! if (mode == VIDEO_PALETTE_GREY) {
! if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {
! /* these aren't valid on the OV6620/OV7620/6630? */
! i2c_w_mask(ov, 0x0e, 0x40, 0x40);
! }
! i2c_w_mask(ov, 0x13, 0x20, 0x20);
! } else {
! if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {
! /* not valid on the OV6620/OV7620/6630? */
! i2c_w_mask(ov, 0x0e, 0x00, 0x40);
! }
! i2c_w_mask(ov, 0x13, 0x00, 0x20);
! }
!
! /******** Clock programming ********/
!
! // FIXME: Test this with OV6630
!
! /* The OV6620 needs special handling. This prevents the
! * severe banding that normally occurs */
! if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)
! {
! /* Clock down */
!
! i2c_w(ov, 0x2a, 0x04);
!
! if (ov->compress) {
! // clock = 0; /* This ensures the highest frame rate */
! clock = 3;
! } else if (clockdiv == -1) { /* If user didn't override it */
! clock = 3; /* Gives better exposure time */
! } else {
! clock = clockdiv;
! }
!
! PDEBUG(4, "Setting clock divisor to %d", clock);
!
! i2c_w(ov, 0x11, clock);
!
! i2c_w(ov, 0x2a, 0x84);
! /* This next setting is critical. It seems to improve
! * the gain or the contrast. The "reserved" bits seem
! * to have some effect in this case. */
! i2c_w(ov, 0x2d, 0x85);
! }
! else
! {
! if (ov->compress) {
! clock = 1; /* This ensures the highest frame rate */
! } else if (clockdiv == -1) { /* If user didn't override it */
! /* Calculate and set the clock divisor */
! clock = ((sub_flag ? ov->subw * ov->subh
! : width * height)
! * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2)
! / 66000;
! } else {
! clock = clockdiv;
! }
!
! PDEBUG(4, "Setting clock divisor to %d", clock);
!
! i2c_w(ov, 0x11, clock);
! }
!
! /******** Special Features ********/
!
! if (framedrop >= 0)
! i2c_w(ov, 0x16, framedrop);
!
! if (sensor_gbr)
! i2c_w_mask(ov, 0x12, 0x08, 0x08);
! else
! i2c_w_mask(ov, 0x12, 0x00, 0x08);
!
! /* Test Pattern */
! i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02);
!
! /* Auto white balance */
! // if (awb)
! i2c_w_mask(ov, 0x12, 0x04, 0x04);
! // else
! // i2c_w_mask(ov, 0x12, 0x00, 0x04);
!
! // This will go away as soon as ov51x_mode_init_sensor_regs()
! // is fully tested.
! /* 7620/6620/6630? don't have register 0x35, so play it safe */
! if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {
! if (width == 640 && height == 480)
! i2c_w(ov, 0x35, 0x9e);
! else
! i2c_w(ov, 0x35, 0x1e);
! }
!
! return 0;
! }
!
! static int
! set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,
! int sub_flag)
! {
! int ret;
! int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
! int hoffset, voffset, hwscale = 0, vwscale = 0;
!
! /* The different sensor ICs handle setting up of window differently.
! * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV76BE:
! hwsbase = 0x38;
! hwebase = 0x3a;
! vwsbase = vwebase = 0x05;
! break;
! case SEN_OV6620:
! case SEN_OV6630:
! hwsbase = 0x38;
! hwebase = 0x3a;
! vwsbase = 0x05;
! vwebase = 0x06;
! break;
! case SEN_OV7620:
! hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
! hwebase = 0x2f;
! vwsbase = vwebase = 0x05;
! break;
! default:
! err("Invalid sensor");
! return -EINVAL;
! }
!
! if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) {
! /* Note: OV518(+) does downsample on its own) */
! if ((width > 176 && height > 144)
! || ov->bclass == BCL_OV518) { /* CIF */
! ret = mode_init_ov_sensor_regs(ov, width, height,
! mode, sub_flag, 0);
! if (ret < 0)
! return ret;
! hwscale = 1;
! vwscale = 1; /* The datasheet says 0; it's wrong */
! hwsize = 352;
! vwsize = 288;
! } else if (width > 176 || height > 144) {
! err("Illegal dimensions");
! return -EINVAL;
! } else { /* QCIF */
! ret = mode_init_ov_sensor_regs(ov, width, height,
! mode, sub_flag, 1);
! if (ret < 0)
! return ret;
! hwsize = 176;
! vwsize = 144;
! }
! } else {
! if (width > 320 && height > 240) { /* VGA */
! ret = mode_init_ov_sensor_regs(ov, width, height,
! mode, sub_flag, 0);
! if (ret < 0)
! return ret;
! hwscale = 2;
! vwscale = 1;
! hwsize = 640;
! vwsize = 480;
! } else if (width > 320 || height > 240) {
! err("Illegal dimensions");
! return -EINVAL;
! } else { /* QVGA */
! ret = mode_init_ov_sensor_regs(ov, width, height,
! mode, sub_flag, 1);
! if (ret < 0)
! return ret;
! hwscale = 1;
! hwsize = 320;
! vwsize = 240;
! }
! }
!
! /* Center the window */
! hoffset = ((hwsize - width) / 2) >> hwscale;
! voffset = ((vwsize - height) / 2) >> vwscale;
!
! /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
! if (sub_flag) {
! i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale));
! i2c_w(ov, 0x18, hwebase+((ov->subx+ov->subw)>>hwscale));
! i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale));
! i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale));
! } else {
! i2c_w(ov, 0x17, hwsbase + hoffset);
! i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale));
! i2c_w(ov, 0x19, vwsbase + voffset);
! i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale));
! }
!
! #ifdef OV511_DEBUG
! if (dump_sensor)
! dump_i2c_regs(ov);
! #endif
! return 0;
}
! /* Set up the OV511/OV511+ with the given image parameters.
! *
! * Do not put any sensor-specific code in here (including I2C I/O functions)
! */
! static int
! ov511_mode_init_regs(struct usb_ov511 *ov,
! int width, int height, int mode, int sub_flag)
{
! int hsegs, vsegs;
! if (sub_flag) {
! width = ov->subw;
! height = ov->subh;
! }
! PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
! width, height, mode, sub_flag);
! // FIXME: This should be moved to a 7111a-specific function once
! // subcapture is dealt with properly
! if (ov->sensor == SEN_SAA7111A) {
! if (width == 320 && height == 240) {
! /* No need to do anything special */
! } else if (width == 640 && height == 480) {
! /* Set the OV511 up as 320x480, but keep the
! * V4L resolution as 640x480 */
! width = 320;
! } else {
! err("SAA7111A only allows 320x240 or 640x480");
return -EINVAL;
}
! }
!
! /* Make sure width and height are a multiple of 8 */
! if (width % 8 || height % 8) {
! err("Invalid size (%d, %d) (mode = %d)", width, height, mode);
! return -EINVAL;
! }
!
! if (width < ov->minwidth || height < ov->minheight) {
! err("Requested dimensions are too small");
return -EINVAL;
}
! if (ov51x_stop(ov) < 0)
! return -EIO;
! if (mode == VIDEO_PALETTE_GREY) {
! reg_w(ov, R511_CAM_UV_EN, 0x00);
! reg_w(ov, R511_SNAP_UV_EN, 0x00);
! reg_w(ov, R511_SNAP_OPTS, 0x01);
! } else {
! reg_w(ov, R511_CAM_UV_EN, 0x01);
! reg_w(ov, R511_SNAP_UV_EN, 0x01);
! reg_w(ov, R511_SNAP_OPTS, 0x03);
}
! /* Here I'm assuming that snapshot size == image size.
! * I hope that's always true. --claudio
! */
! hsegs = (width >> 3) - 1;
! vsegs = (height >> 3) - 1;
! reg_w(ov, R511_CAM_PXCNT, hsegs);
! reg_w(ov, R511_CAM_LNCNT, vsegs);
! reg_w(ov, R511_CAM_PXDIV, 0x00);
! reg_w(ov, R511_CAM_LNDIV, 0x00);
!
! /* YUV420, low pass filer on */
! reg_w(ov, R511_CAM_OPTS, 0x03);
!
! /* Snapshot additions */
! reg_w(ov, R511_SNAP_PXCNT, hsegs);
! reg_w(ov, R511_SNAP_LNCNT, vsegs);
! reg_w(ov, R511_SNAP_PXDIV, 0x00);
! reg_w(ov, R511_SNAP_LNDIV, 0x00);
!
! if (ov->compress) {
! /* Enable Y and UV quantization and compression */
! reg_w(ov, R511_COMP_EN, 0x07);
! reg_w(ov, R511_COMP_LUT_EN, 0x03);
! ov51x_reset(ov, OV511_RESET_OMNICE);
! }
! if (ov51x_restart(ov) < 0)
return -EIO;
return 0;
}
- /* Sets up the OV518/OV518+ with the given image parameters
- *
- * OV518 needs a completely different approach, until we can figure out what
- * the individual registers do. Also, only 15 FPS is supported now.
- *
- * Do not put any sensor-specific code in here (including I2C I/O functions)
- */
- static int
- ov518_mode_init_regs(struct usb_ov511 *ov,
- int width, int height, int mode, int sub_flag)
- {
- int hsegs, vsegs, hi_res;
-
- if (sub_flag) {
- width = ov->subw;
- height = ov->subh;
- }
! PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
! width, height, mode, sub_flag);
! if (width % 16 || height % 8) {
! err("Invalid size (%d, %d)", width, height);
! return -EINVAL;
! }
! if (width < ov->minwidth || height < ov->minheight) {
! err("Requested dimensions are too small");
! return -EINVAL;
! }
! if (width >= 320 && height >= 240) {
! hi_res = 1;
! } else if (width >= 320 || height >= 240) {
! err("Invalid width/height combination (%d, %d)", width, height);
! return -EINVAL;
! } else {
! hi_res = 0;
! }
! if (ov51x_stop(ov) < 0)
return -EIO;
! /******** Set the mode ********/
!
! reg_w(ov, 0x2b, 0);
! reg_w(ov, 0x2c, 0);
! reg_w(ov, 0x2d, 0);
! reg_w(ov, 0x2e, 0);
! reg_w(ov, 0x3b, 0);
! reg_w(ov, 0x3c, 0);
! reg_w(ov, 0x3d, 0);
! reg_w(ov, 0x3e, 0);
! reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);
! reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);
! hsegs = width / 16;
! vsegs = height / 4;
! reg_w(ov, 0x29, hsegs);
! reg_w(ov, 0x2a, vsegs);
! reg_w(ov, 0x39, hsegs);
! reg_w(ov, 0x3a, vsegs);
! /* Windows driver does this here; who knows why */
! reg_w(ov, 0x2f, 0x80);
! /******** Set the framerate (to 15 FPS) ********/
! /* Mode independent, but framerate dependent, regs */
! reg_w(ov, 0x51, 0x02); /* Clock divider; lower==faster */
! reg_w(ov, 0x22, 0x18);
! reg_w(ov, 0x23, 0xff);
! if (ov->bridge == BRG_OV518PLUS)
! reg_w(ov, 0x21, 0x19);
! else
! reg_w(ov, 0x71, 0x19); /* Compression-related? */
! // FIXME: Sensor-specific
! /* Bit 5 is what matters here. Of course, it is "reserved" */
! i2c_w(ov, 0x54, 0x23);
!
! reg_w(ov, 0x2f, 0x80);
!
! if (ov->bridge == BRG_OV518PLUS) {
! reg_w(ov, 0x24, 0x94);
! reg_w(ov, 0x25, 0x90);
! ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */
! ov518_reg_w32(ov, 0xc6, 540, 2); /* 21ch */
! ov518_reg_w32(ov, 0xc7, 540, 2); /* 21ch */
! ov518_reg_w32(ov, 0xc8, 108, 2); /* 6ch */
! ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */
! ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */
! ov518_reg_w32(ov, 0xcc, 2400, 2); /* 960h */
! ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */
! ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */
! } else {
! reg_w(ov, 0x24, 0x9f);
! reg_w(ov, 0x25, 0x90);
! ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */
! ov518_reg_w32(ov, 0xc6, 500, 2); /* 1f4h */
! ov518_reg_w32(ov, 0xc7, 500, 2); /* 1f4h */
! ov518_reg_w32(ov, 0xc8, 142, 2); /* 8eh */
! ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */
! ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */
! ov518_reg_w32(ov, 0xcc, 2000, 2); /* 7d0h */
! ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */
! ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */
}
! reg_w(ov, 0x2f, 0x80);
!
! if (ov51x_restart(ov) < 0)
! return -EIO;
!
! /* Reset it just for good measure */
! if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
return -EIO;
return 0;
}
! /* This is a wrapper around the OV511, OV518, and sensor specific functions */
! static int
! mode_init_regs(struct usb_ov511 *ov,
! int width, int height, int mode, int sub_flag)
{
! int rc = 0;
!
! if (!ov || !ov->dev)
! return -EFAULT;
!
! if (ov->bclass == BCL_OV518) {
! rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag);
! } else {
! rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag);
! }
!
! if (FATAL_ERROR(rc))
! return rc;
! switch (ov->sensor) {
! case SEN_OV7610:
! case SEN_OV7620:
! case SEN_OV76BE:
! case SEN_OV8600:
! case SEN_OV6620:
! case SEN_OV6630:
! rc = set_ov_sensor_window(ov, width, height, mode, sub_flag);
! break;
! case SEN_KS0127:
! case SEN_KS0127B:
! err("KS0127-series decoders not supported yet");
! rc = -EINVAL;
! break;
! case SEN_SAA7111A:
! // rc = mode_init_saa_sensor_regs(ov, width, height, mode,
! // sub_flag);
! PDEBUG(1, "SAA status = 0x%02X", i2c_r(ov, 0x1f));
! break;
! default:
! err("Unknown sensor");
! rc = -EINVAL;
! }
! if (FATAL_ERROR(rc))
! return rc;
! /* Sensor-independent settings */
! rc = sensor_set_auto_brightness(ov, ov->auto_brt);
! if (FATAL_ERROR(rc))
! return rc;
! rc = sensor_set_auto_exposure(ov, ov->auto_exp);
! if (FATAL_ERROR(rc))
! return rc;
! rc = sensor_set_banding_filter(ov, bandingfilter);
! if (FATAL_ERROR(rc))
! return rc;
! if (ov->lightfreq) {
! rc = sensor_set_light_freq(ov, lightfreq);
! if (FATAL_ERROR(rc))
! return rc;
! }
! rc = sensor_set_backlight(ov, ov->backlight);
! if (FATAL_ERROR(rc))
! return rc;
! rc = sensor_set_mirror(ov, ov->mirror);
! if (FATAL_ERROR(rc))
! return rc;
return 0;
}
! /* This sets the default image parameters. This is useful for apps that use
! * read() and do not set these.
*/
static int
! ov51x_set_default_params(struct usb_ov511 *ov)
{
int i;
! /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
! * (using read() instead). */
! for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].width = ov->maxwidth;
! ov->frame[i].height = ov->maxheight;
! ov->frame[i].bytes_read = 0;
! if (force_palette)
! ov->frame[i].format = force_palette;
! else
! ov->frame[i].format = VIDEO_PALETTE_RGB24;
!
! ov->frame[i].depth = get_depth(ov->frame[i].format);
! }
! PDEBUG(3, "%dx%d, %s", ov->maxwidth, ov->maxheight,
! symbolic(v4l1_plist, ov->frame[0].format));
! /* Initialize to max width/height, YUV420 or RGB24 (if supported) */
! if (mode_init_regs(ov, ov->maxwidth, ov->maxheight,
! ov->frame[0].format, 0) < 0)
return -EINVAL;
! return 0;
! }
! /**********************************************************************
! *
! * Video decoder stuff
! *
! **********************************************************************/
! /* Set analog input port of decoder */
! static int
! decoder_set_input(struct usb_ov511 *ov, int input)
! {
! PDEBUG(4, "port %d", input);
! switch (ov->sensor) {
! case SEN_SAA7111A:
! {
! /* Select mode */
! i2c_w_mask(ov, 0x02, input, 0x07);
! /* Bypass chrominance trap for modes 4..7 */
! i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80);
break;
- }
default:
return -EINVAL;
}
! return 0;
! }
!
! /* Get ASCII name of video input */
! static int
! decoder_get_input_name(struct usb_ov511 *ov, int input, char *name)
! {
! switch (ov->sensor) {
! case SEN_SAA7111A:
! {
! if (input < 0 || input > 7)
! return -EINVAL;
! else if (input < 4)
! sprintf(name, "CVBS-%d", input);
! else // if (input < 8)
! sprintf(name, "S-Video-%d", input - 4);
! break;
}
! default:
! sprintf(name, "%s", "Camera");
}
! return 0;
! }
! /* Set norm (NTSC, PAL, SECAM, AUTO) */
! static int
! decoder_set_norm(struct usb_ov511 *ov, int norm)
! {
! PDEBUG(4, "%d", norm);
! switch (ov->sensor) {
! case SEN_SAA7111A:
! {
! int reg_8, reg_e;
! if (norm == VIDEO_MODE_NTSC) {
! reg_8 = 0x40; /* 60 Hz */
! reg_e = 0x00; /* NTSC M / PAL BGHI */
! } else if (norm == VIDEO_MODE_PAL) {
! reg_8 = 0x00; /* 50 Hz */
! reg_e = 0x00; /* NTSC M / PAL BGHI */
! } else if (norm == VIDEO_MODE_AUTO) {
! reg_8 = 0x80; /* Auto field detect */
! reg_e = 0x00; /* NTSC M / PAL BGHI */
! } else if (norm == VIDEO_MODE_SECAM) {
! reg_8 = 0x00; /* 50 Hz */
! reg_e = 0x50; /* SECAM / PAL 4.43 */
! } else {
! return -EINVAL;
! }
- i2c_w_mask(ov, 0x08, reg_8, 0xc0);
- i2c_w_mask(ov, 0x0e, reg_e, 0x70);
break;
}
! default:
return -EINVAL;
}
return 0;
}
--- 474,1134 ----
/**********************************************************************
*
! * Camera interface
*
**********************************************************************/
! static int ov511_reg_write(struct usb_device *dev,
! unsigned char reg,
! unsigned char value)
{
int rc;
! rc = usb_control_msg(dev,
! usb_sndctrlpipe(dev, 0),
! 2 /* REG_IO */,
! USB_TYPE_CLASS | USB_RECIP_DEVICE,
! 0, (__u16)reg, &value, 1, HZ);
! PDEBUG(5, "reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc);
if (rc < 0)
! err("reg write: error %d", rc);
return rc;
}
/* returns: negative is error, pos or zero is data */
! static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
{
int rc;
+ unsigned char buffer[1];
! rc = usb_control_msg(dev,
! usb_rcvctrlpipe(dev, 0),
! 2 /* REG_IO */,
! USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
! 0, (__u16)reg, buffer, 1, HZ);
!
! PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]);
!
if (rc < 0) {
! err("reg read: error %d", rc);
! return rc;
} else {
! return buffer[0];
}
}
! static int ov511_i2c_write(struct usb_device *dev,
! unsigned char reg,
! unsigned char value)
{
int rc, retries;
! PDEBUG(5, "i2c write: 0x%02X:0x%02X", reg, value);
/* Three byte write cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
! rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
! if (rc < 0) goto error;
/* Write "value" to I2C data port of OV511 */
! rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);
! if (rc < 0) goto error;
/* Initiate 3-byte write cycle */
! rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);
! if (rc < 0) goto error;
! do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
! if (rc < 0) goto error;
if ((rc&2) == 0) /* Ack? */
break;
#if 0
! /* I2C abort */
! ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
#endif
if (--retries < 0) {
err("i2c write retries exhausted");
! rc = -1;
! goto error;
}
}
return 0;
! error:
! err("i2c write: error %d", rc);
! return rc;
}
! /* returns: negative is error, pos or zero is data */
! static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
{
int rc, value, retries;
/* Two byte write cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
! rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
! if (rc < 0) goto error;
/* Initiate 2-byte write cycle */
! rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);
! if (rc < 0) goto error;
! do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
! if (rc < 0) goto error;
if ((rc&2) == 0) /* Ack? */
break;
! /* I2C abort */
! ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
if (--retries < 0) {
err("i2c write retries exhausted");
! rc = -1;
! goto error;
}
}
/* Two byte read cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Initiate 2-byte read cycle */
! rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
! if (rc < 0) goto error;
! do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
! if (rc < 0) goto error;
if ((rc&2) == 0) /* Ack? */
break;
! /* I2C abort */
! rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
! if (rc < 0) goto error;
if (--retries < 0) {
err("i2c read retries exhausted");
! rc = -1;
! goto error;
}
}
! value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
! PDEBUG(5, "i2c read: 0x%02X:0x%02X", reg, value);
!
! /* This is needed to make ov511_i2c_write() work */
! rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
if (rc < 0)
! goto error;
!
return value;
+
+ error:
+ err("i2c read: error %d", rc);
+ return rc;
}
! static int ov511_write_regvals(struct usb_device *dev,
! struct ov511_regvals * pRegvals)
{
int rc;
! while (pRegvals->bus != OV511_DONE_BUS) {
! if (pRegvals->bus == OV511_REG_BUS) {
! if ((rc = ov511_reg_write(dev, pRegvals->reg,
! pRegvals->val)) < 0)
! goto error;
! } else if (pRegvals->bus == OV511_I2C_BUS) {
! if ((rc = ov511_i2c_write(dev, pRegvals->reg,
! pRegvals->val)) < 0)
! goto error;
! } else {
! err("Bad regval array");
! rc = -1;
! goto error;
! }
! pRegvals++;
! }
! return 0;
+ error:
+ err("write regvals: error %d", rc);
return rc;
}
! #ifdef OV511_DEBUG
! static void ov511_dump_i2c_range(struct usb_device *dev, int reg1, int regn)
{
int i;
int rc;
! for(i = reg1; i <= regn; i++) {
! rc = ov511_i2c_read(dev, i);
! PDEBUG(1, "OV7610[0x%X] = 0x%X", i, rc);
}
}
! static void ov511_dump_i2c_regs(struct usb_device *dev)
{
! PDEBUG(3, "I2C REGS");
! ov511_dump_i2c_range(dev, 0x00, 0x7C);
}
! #if 0
! static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn)
{
int i;
int rc;
! for(i = reg1; i <= regn; i++) {
! rc = ov511_reg_read(dev, i);
! PDEBUG(1, "OV511[0x%X] = 0x%X", i, rc);
}
}
! static void ov511_dump_regs(struct usb_device *dev)
{
! PDEBUG(1, "CAMERA INTERFACE REGS");
! ov511_dump_reg_range(dev, 0x10, 0x1f);
! PDEBUG(1, "DRAM INTERFACE REGS");
! ov511_dump_reg_range(dev, 0x20, 0x23);
! PDEBUG(1, "ISO FIFO REGS");
! ov511_dump_reg_range(dev, 0x30, 0x31);
! PDEBUG(1, "PIO REGS");
! ov511_dump_reg_range(dev, 0x38, 0x39);
! ov511_dump_reg_range(dev, 0x3e, 0x3e);
! PDEBUG(1, "I2C REGS");
! ov511_dump_reg_range(dev, 0x40, 0x49);
! PDEBUG(1, "SYSTEM CONTROL REGS");
! ov511_dump_reg_range(dev, 0x50, 0x55);
! ov511_dump_reg_range(dev, 0x5e, 0x5f);
! PDEBUG(1, "OmniCE REGS");
! ov511_dump_reg_range(dev, 0x70, 0x79);
! ov511_dump_reg_range(dev, 0x80, 0x9f);
! ov511_dump_reg_range(dev, 0xa0, 0xbf);
}
#endif
#endif
! static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
{
! int rc;
!
! PDEBUG(4, "Reset: type=0x%X", reset_type);
! rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
! rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
! if (rc < 0)
! err("reset: command failed");
return rc;
}
! /* Temporarily stops OV511 from functioning. Must do this before changing
! * registers while the camera is streaming */
! static inline int ov511_stop(struct usb_device *dev)
! {
! PDEBUG(4, "stopping");
! return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
! }
! /* Restarts OV511 after ov511_stop() is called */
! static inline int ov511_restart(struct usb_device *dev)
! {
! PDEBUG(4, "restarting");
! return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
}
! static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
{
! int alt, mult;
! if (ov511_stop(ov511->dev) < 0)
! return -EIO;
! mult = size >> 5;
! if (ov511->bridge == BRG_OV511) {
! if (size == 0) alt = OV511_ALT_SIZE_0;
! else if (size == 257) alt = OV511_ALT_SIZE_257;
! else if (size == 513) alt = OV511_ALT_SIZE_513;
! else if (size == 769) alt = OV511_ALT_SIZE_769;
! else if (size == 993) alt = OV511_ALT_SIZE_993;
! else {
! err("Set packet size: invalid size (%d)", size);
return -EINVAL;
}
! } else if (ov511->bridge == BRG_OV511PLUS) {
! if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
! else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
! else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
! else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;
! else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;
! else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;
! else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;
! else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;
! else {
! err("Set packet size: invalid size (%d)", size);
! return -EINVAL;
! }
! } else {
! err("Set packet size: Invalid bridge type");
return -EINVAL;
}
! PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
! if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, mult) < 0)
! return -ENOMEM;
!
! if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
! err("Set packet size: set interface error");
! return -EBUSY;
}
! // FIXME - Should we only reset the FIFO?
! if (ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0)
! return -ENOMEM;
! ov511->packet_size = size;
! if (ov511_restart(ov511->dev) < 0)
return -EIO;
return 0;
}
! static inline int
! ov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
! {
! int ret;
! struct usb_device *dev = ov511->dev;
! PDEBUG(4, "ov511_set_picture");
! if (ov511_stop(dev) < 0)
! return -EIO;
! ov511->contrast = p->contrast;
! ov511->brightness = p->brightness;
! ov511->colour = p->colour;
! ov511->hue = p->hue;
! ov511->whiteness = p->whiteness;
! if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
return -EIO;
+ #if 0
+ /* disable auto adjust mode */
+ if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
+ return -EIO;
+ #endif
+ if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE
+ || ov511->sensor == SEN_OV6620)
+ if (ov511_i2c_write(dev, OV7610_REG_SAT, p->colour >> 8) < 0)
+ return -EIO;
! if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV6620) {
! if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
! return -EIO;
! if (ov511_i2c_write(dev, OV7610_REG_RED, 0xFF - (p->hue >> 8)) < 0)
! return -EIO;
! if (ov511_i2c_write(dev, OV7610_REG_BLUE, p->hue >> 8) < 0)
! return -EIO;
! if (ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
! return -EIO;
! } else if ((ov511->sensor == SEN_OV7620)
! || (ov511->sensor == SEN_OV7620AE)) {
! #if 0
! int cur_sat, new_sat, tmp;
! cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE);
! tmp = (p->hue >> 8) - cur_sat;
! new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp;
! PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp);
! if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0)
! return -EIO;
! // DEBUG_CODE
! PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE));
! #endif
}
! if (ov511_restart(dev) < 0)
return -EIO;
return 0;
}
! static inline int
! ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
{
! int ret;
! struct usb_device *dev = ov511->dev;
! PDEBUG(4, "ov511_get_picture");
! if (ov511_stop(dev) < 0)
! return -EIO;
! if ((ret = ov511_i2c_read(dev, OV7610_REG_SAT)) < 0) return -EIO;
! p->colour = ret << 8;
! if ((ret = ov511_i2c_read(dev, OV7610_REG_CNT)) < 0) return -EIO;
! p->contrast = ret << 8;
! if ((ret = ov511_i2c_read(dev, OV7610_REG_BRT)) < 0) return -EIO;
! p->brightness = ret << 8;
! /* This may not be the best way to do it */
! if ((ret = ov511_i2c_read(dev, OV7610_REG_BLUE)) < 0) return -EIO;
! p->hue = ret << 8;
! p->whiteness = 105 << 8;
! /* Can we get these from frame[0]? -claudio? */
! p->depth = ov511->frame[0].depth;
! p->palette = ov511->frame[0].format;
! if (ov511_restart(dev) < 0)
! return -EIO;
return 0;
}
! /* Returns number of bits per pixel (regardless of where they are located; planar or
! * not), or zero for unsupported format.
*/
+ static int ov511_get_depth(int palette)
+ {
+ switch (palette) {
+ case VIDEO_PALETTE_GREY: return 8;
+ case VIDEO_PALETTE_RGB565: return 16;
+ case VIDEO_PALETTE_RGB24: return 24;
+ case VIDEO_PALETTE_YUV422: return 16;
+ case VIDEO_PALETTE_YUYV: return 16;
+ case VIDEO_PALETTE_YUV420: return 24;
+ case VIDEO_PALETTE_YUV422P: return 24; /* Planar */
+ default: return 0; /* Invalid format */
+ }
+ }
+
+ /* LNCNT values fixed by Lawrence Glaister */
+ static struct mode_list mlist[] = {
+ /* W H C PXCNT LNCNT PXDIV LNDIV M420 COMA COML */
+ { 640, 480, 0, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },
+ { 640, 480, 1, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },
+ { 320, 240, 0, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 320, 240, 1, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 352, 288, 0, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 352, 288, 1, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 384, 288, 0, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 384, 288, 1, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 448, 336, 0, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 448, 336, 1, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 176, 144, 0, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 176, 144, 1, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 160, 120, 0, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 160, 120, 1, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },
+ { 0, 0 }
+ };
+
static int
! ov511_mode_init_regs(struct usb_ov511 *ov511,
! int width, int height, int mode, int sub_flag)
{
int i;
+ struct usb_device *dev = ov511->dev;
+ int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
+ int hwscale = 0, vwscale = 0;
! PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
! width, height, mode, sub_flag);
! if (ov511_stop(ov511->dev) < 0)
! return -EIO;
! /* Dumppix only works with RGB24 */
! if (dumppix && (mode != VIDEO_PALETTE_RGB24)) {
! err("dumppix only supported with RGB 24");
return -EINVAL;
+ }
! if (mode == VIDEO_PALETTE_GREY) {
! ov511_reg_write(dev, 0x16, 0x00);
! if (ov511->sensor == SEN_OV7610
! || ov511->sensor == SEN_OV7620AE) {
! /* these aren't valid on the OV6620/OV7620 */
! ov511_i2c_write(dev, 0x0e, 0x44);
! }
! ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);
! /* For snapshot */
! ov511_reg_write(dev, 0x1e, 0x00);
! ov511_reg_write(dev, 0x1f, 0x01);
! } else {
! ov511_reg_write(dev, 0x16, 0x01);
! if (ov511->sensor == SEN_OV7610
! || ov511->sensor == SEN_OV7620AE) {
! /* not valid on the OV6620/OV7620 */
! ov511_i2c_write(dev, 0x0e, 0x04);
! }
! ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);
! /* For snapshot */
! ov511_reg_write(dev, 0x1e, 0x01);
! ov511_reg_write(dev, 0x1f, 0x03);
! }
! /* The different sensor ICs handle setting up of window differently */
! switch (ov511->sensor) {
! case SEN_OV7610:
! case SEN_OV7620AE:
! hwsbase = 0x38;
! hwebase = 0x3a;
! vwsbase = vwebase = 0x05;
! break;
! case SEN_OV6620:
! hwsbase = 0x38;
! hwebase = 0x3a;
! vwsbase = 0x05;
! vwebase = 0x06;
! break;
! case SEN_OV7620:
! hwsbase = 0x2c;
! hwebase = 0x2d;
! vwsbase = vwebase = 0x05;
break;
default:
+ err("Invalid sensor");
return -EINVAL;
}
! /* Bit 5 of COM C register varies with sensor */
! if (ov511->sensor == SEN_OV6620) {
! if (width > 176 && height > 144) { /* CIF */
! ov511_i2c_write(dev, 0x14, 0x04);
! hwscale = 1;
! vwscale = 1; /* The datasheet says 0; it's wrong */
! hwsize = 352;
! vwsize = 288;
! } else { /* QCIF */
! ov511_i2c_write(dev, 0x14, 0x24);
! hwsize = 176;
! vwsize = 144;
! }
}
! else {
! if (width > 320 && height > 240) { /* VGA */
! ov511_i2c_write(dev, 0x14, 0x04);
! hwscale = 2;
! vwscale = 1;
! hwsize = 640;
! vwsize = 480;
! } else { /* QVGA */
! ov511_i2c_write(dev, 0x14, 0x24);
! hwscale = 1;
! hwsize = 320;
! vwsize = 240;
! }
}
! /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
! if (sub_flag) {
! ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>hwscale));
! ov511_i2c_write(dev, 0x18, hwebase+((ov511->subx+ov511->subw)>>hwscale));
! ov511_i2c_write(dev, 0x19, vwsbase+(ov511->suby>>vwscale));
! ov511_i2c_write(dev, 0x1a, vwebase+((ov511->suby+ov511->subh)>>vwscale));
! } else {
! ov511_i2c_write(dev, 0x17, hwsbase);
! ov511_i2c_write(dev, 0x18, hwebase + (hwsize>>hwscale));
! ov511_i2c_write(dev, 0x19, vwsbase);
! ov511_i2c_write(dev, 0x1a, vwebase + (vwsize>>vwscale));
! }
! for (i = 0; mlist[i].width; i++) {
! int lncnt, pxcnt, clock;
! if (width != mlist[i].width || height != mlist[i].height)
! continue;
! if (!mlist[i].color && mode != VIDEO_PALETTE_GREY)
! continue;
!
! /* Here I'm assuming that snapshot size == image size.
! * I hope that's always true. --claudio
! */
! pxcnt = sub_flag ? (ov511->subw >> 3) - 1 : mlist[i].pxcnt;
! lncnt = sub_flag ? (ov511->subh >> 3) - 1 : mlist[i].lncnt;
!
! ov511_reg_write(dev, 0x12, pxcnt);
! ov511_reg_write(dev, 0x13, lncnt);
! ov511_reg_write(dev, 0x14, mlist[i].pxdv);
! ov511_reg_write(dev, 0x15, mlist[i].lndv);
! ov511_reg_write(dev, 0x18, mlist[i].m420);
!
! /* Snapshot additions */
! ov511_reg_write(dev, 0x1a, pxcnt);
! ov511_reg_write(dev, 0x1b, lncnt);
! ov511_reg_write(dev, 0x1c, mlist[i].pxdv);
! ov511_reg_write(dev, 0x1d, mlist[i].lndv);
!
! /* Calculate and set the clock divisor */
! clock = ((sub_flag ? ov511->subw * ov511->subh : width * height)
! * (mlist[i].color ? 3 : 2) / 2) / 66000;
! #if 0
! clock *= cams;
! #endif
! ov511_i2c_write(dev, 0x11, clock);
!
! /* We only have code to convert GBR -> RGB24 */
! if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
! ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x0a:0x08));
! else
! ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00));
!
! /* 7620/6620 don't have register 0x35, so play it safe */
! if (ov511->sensor == SEN_OV7610 ||
! ov511->sensor == SEN_OV7620AE)
! ov511_i2c_write(dev, 0x35, mlist[i].common_L);
break;
}
!
! if (compress) {
! ov511_reg_write(dev, 0x78, 0x03); // Turn on Y compression
! ov511_reg_write(dev, 0x79, 0x00); // Disable LUTs
! }
!
! if (ov511_restart(ov511->dev) < 0)
! return -EIO;
!
! if (mlist[i].width == 0) {
! err("Unknown mode (%d, %d): %d", width, height, mode);
return -EINVAL;
}
+ #ifdef OV511_DEBUG
+ if (debug >= 5)
+ ov511_dump_i2c_regs(dev);
+ #endif
+
return 0;
}
***************
*** 3073,3094 ****
* coefficients are scaled into 16.16 fixed-point integers.
* They were determined as follows:
*
! * double brightness = 1.0; (0->black; 1->full scale)
* double saturation = 1.0; (0->greyscale; 1->full color)
* double fixScale = brightness * 256 * 256;
* int rvScale = (int)(1.402 * saturation * fixScale);
* int guScale = (int)(-0.344136 * saturation * fixScale);
* int gvScale = (int)(-0.714136 * saturation * fixScale);
* int buScale = (int)(1.772 * saturation * fixScale);
! * int yScale = (int)(fixScale);
*/
/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
static inline void
! move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
! int rowPixels, unsigned char * rgb, int bits)
{
const int rvScale = 91881;
const int guScale = -22553;
--- 1154,1175 ----
* coefficients are scaled into 16.16 fixed-point integers.
* They were determined as follows:
*
! * double brightness = 1.0; (0->black; 1->full scale)
* double saturation = 1.0; (0->greyscale; 1->full color)
* double fixScale = brightness * 256 * 256;
* int rvScale = (int)(1.402 * saturation * fixScale);
* int guScale = (int)(-0.344136 * saturation * fixScale);
* int gvScale = (int)(-0.714136 * saturation * fixScale);
* int buScale = (int)(1.772 * saturation * fixScale);
! * int yScale = (int)(fixScale);
*/
/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
static inline void
! ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
! int rowPixels, unsigned char * rgb, int bits)
{
const int rvScale = 91881;
const int guScale = -22553;
***************
*** 3111,3213 ****
if (bits == 24) {
/* Write out top two pixels */
! rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
! rgb[2] = LIMIT(r+yTL);
!
! rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
! rgb[5] = LIMIT(r+yTR);
/* Skip down to next line to write out bottom two pixels */
rgb += 3 * rowPixels;
! rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
! rgb[2] = LIMIT(r+yBL);
!
! rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
! rgb[5] = LIMIT(r+yBR);
! } else if (bits == 16) {
! /* Write out top two pixels */
! rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F)
! | ((LIMIT(g+yTL) << 3) & 0xE0);
! rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07)
! | (LIMIT(r+yTL) & 0xF8);
!
! rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F)
! | ((LIMIT(g+yTR) << 3) & 0xE0);
! rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07)
! | (LIMIT(r+yTR) & 0xF8);
!
! /* Skip down to next line to write out bottom two pixels */
! rgb += 2 * rowPixels;
!
! rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F)
! | ((LIMIT(g+yBL) << 3) & 0xE0);
! rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07)
! | (LIMIT(r+yBL) & 0xF8);
!
! rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F)
! | ((LIMIT(g+yBR) << 3) & 0xE0);
! rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07)
! | (LIMIT(r+yBR) & 0xF8);
! }
! }
!
! /**********************************************************************
! *
! * Raw data parsing
! *
! **********************************************************************/
!
! /* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the
! * image at pOut is specified by w.
! */
! static inline void
! make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
! {
! unsigned char *pOut1 = pOut;
! int x, y;
!
! for (y = 0; y < 8; y++) {
! pOut1 = pOut;
! for (x = 0; x < 8; x++) {
! *pOut1++ = *pIn++;
! }
! pOut += w;
! }
! }
! /*
! * For RAW BW (YUV400) images, data shows up in 256 byte segments.
! * The segments represent 4 squares of 8x8 pixels as follows:
! *
! * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199
! * 8 9 ... 15 72 73 ... 79 200 201 ... 207
! * ... ... ...
! * 56 57 ... 63 120 121 ... 127 248 249 ... 255
! *
! */
! static void
! yuv400raw_to_yuv400p(struct ov511_frame *frame,
! unsigned char *pIn0, unsigned char *pOut0)
! {
! int x, y;
! unsigned char *pIn, *pOut, *pOutLine;
! /* Copy Y */
! pIn = pIn0;
! pOutLine = pOut0;
! for (y = 0; y < frame->rawheight - 1; y += 8) {
! pOut = pOutLine;
! for (x = 0; x < frame->rawwidth - 1; x += 8) {
! make_8x8(pIn, pOut, frame->rawwidth);
! pIn += 64;
! pOut += 8;
! }
! pOutLine += 8 * frame->rawwidth;
}
}
/*
! * For YUV4:2:0 images, the data shows up in 384 byte segments.
* The first 64 bytes of each segment are U, the next 64 are V. The U and
* V are arranged as follows:
*
--- 1192,1225 ----
if (bits == 24) {
/* Write out top two pixels */
! rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
! rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);
/* Skip down to next line to write out bottom two pixels */
rgb += 3 * rowPixels;
! rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
! rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
! } else if (bits == 16) {
! /* Write out top two pixels */
! rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) | ((LIMIT(g+yTL) << 3) & 0xE0);
! rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07) | (LIMIT(r+yTL) & 0xF8);
! rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) | ((LIMIT(g+yTR) << 3) & 0xE0);
! rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) | (LIMIT(r+yTR) & 0xF8);
! /* Skip down to next line to write out bottom two pixels */
! rgb += 2 * rowPixels;
!
! rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F) | ((LIMIT(g+yBL) << 3) & 0xE0);
! rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07) | (LIMIT(r+yBL) & 0xF8);
!
! rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F) | ((LIMIT(g+yBR) << 3) & 0xE0);
! rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07) | (LIMIT(r+yBR) & 0xF8);
}
}
/*
! * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.
* The first 64 bytes of each segment are U, the next 64 are V. The U and
* V are arranged as follows:
*
***************
*** 3227,3235 ****
* 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255
*
* Note that the U and V data in one segment represents a 16 x 16 pixel
! * area, but the Y data represents a 32 x 8 pixel area. If the width is not an
! * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the
! * next horizontal stripe.
*
* If dumppix module param is set, _parse_data just dumps the incoming segments,
* verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
--- 1239,1245 ----
* 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255
*
* Note that the U and V data in one segment represents a 16 x 16 pixel
! * area, but the Y data represents a 32 x 8 pixel area.
*
* If dumppix module param is set, _parse_data just dumps the incoming segments,
* verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
***************
*** 3238,4082 ****
* this data is scrambled.
*/
! /* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0.
! *
! * FIXME: Currently only handles width and height that are multiples of 16
! */
static void
! yuv420raw_to_yuv420p(struct ov511_frame *frame,
! unsigned char *pIn0, unsigned char *pOut0)
{
! int k, x, y;
! unsigned char *pIn, *pOut, *pOutLine;
! const unsigned int a = frame->rawwidth * frame->rawheight;
! const unsigned int w = frame->rawwidth / 2;
- /* Copy U and V */
pIn = pIn0;
! pOutLine = pOut0 + a;
! for (y = 0; y < frame->rawheight - 1; y += 16) {
! pOut = pOutLine;
! for (x = 0; x < frame->rawwidth - 1; x += 16) {
! make_8x8(pIn, pOut, w);
! make_8x8(pIn + 64, pOut + a/4, w);
! pIn += 384;
! pOut += 8;
}
! pOutLine += 8 * w;
}
- /* Copy Y */
pIn = pIn0 + 128;
! pOutLine = pOut0;
! k = 0;
! for (y = 0; y < frame->rawheight - 1; y += 8) {
! pOut = pOutLine;
! for (x = 0; x < frame->rawwidth - 1; x += 8) {
! make_8x8(pIn, pOut, frame->rawwidth);
! pIn += 64;
! pOut += 8;
! if ((++k) > 3) {
! k = 0;
! pIn += 128;
}
}
! pOutLine += 8 * frame->rawwidth;
}
}
- /*
- * fixFrameRGBoffset--
- * My camera seems to return the red channel about 1 pixel
- * low, and the blue channel about 1 pixel high. After YUV->RGB
- * conversion, we can correct this easily. OSL 2/24/2000.
- */
static void
! fixFrameRGBoffset(struct ov511_frame *frame)
! {
! int x, y;
! int rowBytes = frame->width*3, w = frame->width;
! unsigned char *rgb = frame->data;
! const int shift = 1; /* Distance to shift pixels by, vertically */
!
! /* Don't bother with little images */
! if (frame->width < 400)
! return;
!
! /* This only works with RGB24 */
! if (frame->format != VIDEO_PALETTE_RGB24)
! return;
!
! /* Shift red channel up */
! for (y = shift; y < frame->height; y++) {
! int lp = (y-shift)*rowBytes; /* Previous line offset */
! int lc = y*rowBytes; /* Current line offset */
! for (x = 0; x < w; x++)
! rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
! }
!
! /* Shift blue channel down */
! for (y = frame->height-shift-1; y >= 0; y--) {
! int ln = (y + shift) * rowBytes; /* Next line offset */
! int lc = y * rowBytes; /* Current line offset */
! for (x = 0; x < w; x++)
! rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
! }
! }
!
! /**********************************************************************
! *
! * Decompression
! *
! **********************************************************************/
!
! /* Chooses a decompression module, locks it, and sets ov->decomp_ops
! * accordingly. Returns -ENXIO if decompressor is not available, otherwise
! * returns 0 if no other error.
! */
! static int
! request_decompressor(struct usb_ov511 *ov)
{
! if (!ov)
! return -ENODEV;
! if (ov->decomp_ops) {
! err("ERROR: Decompressor already requested!");
! return -EINVAL;
}
! lock_kernel();
!
! /* Try to get MMX, and fall back on no-MMX if necessary */
! if (ov->bclass == BCL_OV511) {
! if (ov511_mmx_decomp_ops) {
! PDEBUG(3, "Using OV511 MMX decompressor");
! ov->decomp_ops = ov511_mmx_decomp_ops;
! } else if (ov511_decomp_ops) {
! PDEBUG(3, "Using OV511 decompressor");
! ov->decomp_ops = ov511_decomp_ops;
! } else {
! err("No decompressor available");
! }
! } else if (ov->bclass == BCL_OV518) {
! if (ov518_mmx_decomp_ops) {
! PDEBUG(3, "Using OV518 MMX decompressor");
! ov->decomp_ops = ov518_mmx_decomp_ops;
! } else if (ov518_decomp_ops) {
! PDEBUG(3, "Using OV518 decompressor");
! ov->decomp_ops = ov518_decomp_ops;
! } else {
! err("No decompressor available");
}
! } else {
! err("Unknown bridge");
}
! if (ov->decomp_ops) {
! if (!ov->decomp_ops->owner) {
! ov->decomp_ops = NULL;
! unlock_kernel();
! return -ENOSYS;
}
- __MOD_INC_USE_COUNT(ov->decomp_ops->owner);
- unlock_kernel();
- return 0;
- } else {
- unlock_kernel();
- return -ENOSYS;
}
}
- /* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
- * if ov->decomp_ops is NULL.
- */
static void
! release_decompressor(struct usb_ov511 *ov)
{
! int released = 0; /* Did we actually do anything? */
!
! if (!ov)
! return;
! lock_kernel();
!
! if (ov->decomp_ops && ov->decomp_ops->owner) {
! __MOD_DEC_USE_COUNT(ov->decomp_ops->owner);
! released = 1;
! }
!
! ov->decomp_ops = NULL;
!
! unlock_kernel();
!
! if (released)
! PDEBUG(3, "Decompressor released");
! }
!
! static void
! decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
! unsigned char *pIn0, unsigned char *pOut0)
! {
! if (!ov->decomp_ops)
! if (request_decompressor(ov))
! return;
!
! PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
!
! if (frame->format == VIDEO_PALETTE_GREY
! && ov->decomp_ops->decomp_400) {
! int ret = ov->decomp_ops->decomp_400(
! pIn0,
! pOut0,
! frame->compbuf,
! frame->rawwidth,
! frame->rawheight,
! frame->bytes_recvd);
! PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
! } else if (frame->format != VIDEO_PALETTE_GREY
! && ov->decomp_ops->decomp_420) {
! int ret = ov->decomp_ops->decomp_420(
! pIn0,
! pOut0,
! frame->compbuf,
! frame->rawwidth,
! frame->rawheight,
! frame->bytes_recvd);
! PDEBUG(4, "DEBUG: decomp_420 returned %d", ret);
! } else {
! err("Decompressor does not support this format");
! }
}
! /**********************************************************************
! *
! * Format conversion
! *
! **********************************************************************/
!
! /* Converts from planar YUV420 to RGB24. */
static void
! yuv420p_to_rgb(struct ov511_frame *frame,
! unsigned char *pIn0, unsigned char *pOut0, int bits)
{
! const int numpix = frame->width * frame->height;
! const int bytes = bits >> 3;
! int i, j, y00, y01, y10, y11, u, v;
! unsigned char *pY = pIn0;
! unsigned char *pU = pY + numpix;
! unsigned char *pV = pU + numpix / 4;
! unsigned char *pOut = pOut0;
!
! for (j = 0; j <= frame->height - 2; j += 2) {
! for (i = 0; i <= frame->width - 2; i += 2) {
! y00 = *pY;
! y01 = *(pY + 1);
! y10 = *(pY + frame->width);
! y11 = *(pY + frame->width + 1);
! u = (*pU++) - 128;
! v = (*pV++) - 128;
!
! move_420_block(y00, y01, y10, y11, u, v,
! frame->width, pOut, bits);
! pY += 2;
! pOut += 2 * bytes;
}
! pY += frame->width;
! pOut += frame->width * bytes;
}
- }
-
- /* Converts from planar YUV420 to YUV422 (YUYV). */
- static void
- yuv420p_to_yuv422(struct ov511_frame *frame,
- unsigned char *pIn0, unsigned char *pOut0)
- {
- const int numpix = frame->width * frame->height;
- int i, j;
- unsigned char *pY = pIn0;
- unsigned char *pU = pY + numpix;
- unsigned char *pV = pU + numpix / 4;
- unsigned char *pOut = pOut0;
-
- for (i = 0; i < numpix; i++) {
- *pOut = *(pY + i);
- pOut += 2;
- }
-
- pOut = pOut0 + 1;
- for (j = 0; j <= frame->height - 2 ; j += 2) {
- for (i = 0; i <= frame->width - 2; i += 2) {
- int u = *pU++;
- int v = *pV++;
*pOut = u;
*(pOut+2) = v;
! *(pOut+frame->width*2) = u;
! *(pOut+frame->width*2+2) = v;
pOut += 4;
}
! pOut += (frame->width * 2);
}
}
- /* Converts pData from planar YUV420 to planar YUV422 **in place**. */
static void
! yuv420p_to_yuv422p(struct ov511_frame *frame, unsigned char *pData)
{
! const int numpix = frame->width * frame->height;
! const int w = frame->width;
! int j;
! unsigned char *pIn, *pOut;
!
! /* Clear U and V */
! memset(pData + numpix + numpix / 2, 127, numpix / 2);
!
! /* Convert V starting from beginning and working forward */
! pIn = pData + numpix + numpix / 4;
! pOut = pData + numpix +numpix / 2;
! for (j = 0; j <= frame->height - 2; j += 2) {
! memmove(pOut, pIn, w/2);
! memmove(pOut + w/2, pIn, w/2);
! pIn += w/2;
pOut += w;
}
! /* Convert U, starting from end and working backward */
! pIn = pData + numpix + numpix / 4;
! pOut = pData + numpix + numpix / 2;
! for (j = 0; j <= frame->height - 2; j += 2) {
! pIn -= w/2;
! pOut -= w;
! memmove(pOut, pIn, w/2);
! memmove(pOut + w/2, pIn, w/2);
}
}
- /* Fuses even and odd fields together, and doubles width.
- * INPUT: an odd field followed by an even field at pIn0, in YUV planar format
- * OUTPUT: a normal YUV planar image, with correct aspect ratio
- */
static void
! deinterlace(struct ov511_frame *frame, int rawformat,
! unsigned char *pIn0, unsigned char *pOut0)
{
! const int fieldheight = frame->rawheight / 2;
! const int fieldpix = fieldheight * frame->rawwidth;
! const int w = frame->width;
! int x, y;
! unsigned char *pInEven, *pInOdd, *pOut;
!
! PDEBUG(5, "fieldheight=%d", fieldheight);
! if (frame->rawheight != frame->height) {
! err("invalid height");
! return;
! }
!
! if ((frame->rawwidth * 2) != frame->width) {
! err("invalid width");
! return;
}
! /* Y */
! pInOdd = pIn0;
! pInEven = pInOdd + fieldpix;
! pOut = pOut0;
! for (y = 0; y < fieldheight; y++) {
! for (x = 0; x < frame->rawwidth; x++) {
! *pOut = *pInEven;
! *(pOut+1) = *pInEven++;
! *(pOut+w) = *pInOdd;
! *(pOut+w+1) = *pInOdd++;
! pOut += 2;
}
! pOut += w;
}
! if (rawformat == RAWFMT_YUV420) {
! /* U */
! pInOdd = pIn0 + fieldpix * 2;
! pInEven = pInOdd + fieldpix / 4;
! for (y = 0; y < fieldheight / 2; y++) {
! for (x = 0; x < frame->rawwidth / 2; x++) {
! *pOut = *pInEven;
! *(pOut+1) = *pInEven++;
! *(pOut+w/2) = *pInOdd;
! *(pOut+w/2+1) = *pInOdd++;
! pOut += 2;
! }
! pOut += w/2;
! }
! /* V */
! pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2;
! pInEven = pInOdd + fieldpix / 4;
! for (y = 0; y < fieldheight / 2; y++) {
! for (x = 0; x < frame->rawwidth / 2; x++) {
! *pOut = *pInEven;
! *(pOut+1) = *pInEven++;
! *(pOut+w/2) = *pInOdd;
! *(pOut+w/2+1) = *pInOdd++;
! pOut += 2;
! }
! pOut += w/2;
}
}
}
static void
! ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame)
{
! /* Deinterlace frame, if necessary */
! if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) {
! if (frame->compressed)
! decompress(ov, frame, frame->rawdata,
! frame->tempdata);
! else
! yuv400raw_to_yuv400p(frame, frame->rawdata,
! frame->tempdata);
! deinterlace(frame, RAWFMT_YUV400, frame->tempdata,
! frame->data);
! } else {
! if (frame->compressed)
! decompress(ov, frame, frame->rawdata,
! frame->data);
! else
! yuv400raw_to_yuv400p(frame, frame->rawdata,
! frame->data);
}
}
! /* Process raw YUV420 data into the format requested by the app. Conversion
! * between V4L formats is allowed.
*/
! static void
! ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame)
{
! /* Process frame->rawdata to frame->tempdata */
! if (frame->compressed)
! decompress(ov, frame, frame->rawdata, frame->tempdata);
! else
! yuv420raw_to_yuv420p(frame, frame->rawdata, frame->tempdata);
! /* Deinterlace frame, if necessary */
! if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) {
! memcpy(frame->rawdata, frame->tempdata,
! MAX_RAW_DATA_SIZE(frame->width, frame->height));
! deinterlace(frame, RAWFMT_YUV420, frame->rawdata,
! frame->tempdata);
! }
!
! /* Frame should be (width x height) and not (rawwidth x rawheight) at
! * this point. */
!
! /* Process frame->tempdata to frame->data */
! switch (frame->format) {
! case VIDEO_PALETTE_RGB565:
! yuv420p_to_rgb(frame, frame->tempdata, frame->data, 16);
! break;
! case VIDEO_PALETTE_RGB24:
! yuv420p_to_rgb(frame, frame->tempdata, frame->data, 24);
! break;
! case VIDEO_PALETTE_YUV422:
! case VIDEO_PALETTE_YUYV:
! yuv420p_to_yuv422(frame, frame->tempdata, frame->data);
! break;
! case VIDEO_PALETTE_YUV420:
! case VIDEO_PALETTE_YUV420P:
! memcpy(frame->data, frame->tempdata,
! MAX_RAW_DATA_SIZE(frame->width, frame->height));
! break;
! case VIDEO_PALETTE_YUV422P:
! /* Data is converted in place, so copy it in advance */
! memcpy(frame->data, frame->tempdata,
! MAX_RAW_DATA_SIZE(frame->width, frame->height));
! yuv420p_to_yuv422p(frame, frame->data);
! break;
! default:
! err("Cannot convert YUV420 to %s",
! symbolic(v4l1_plist, frame->format));
}
! if (fix_rgb_offset)
! fixFrameRGBoffset(frame);
! }
!
! /* Post-processes the specified frame. This consists of:
! * 1. Decompress frame, if necessary
! * 2. Deinterlace frame and scale to proper size, if necessary
! * 3. Convert from YUV planar to destination format, if necessary
! * 4. Fix the RGB offset, if necessary
! */
! static void
! ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
! {
! if (dumppix) {
! memset(frame->data, 0,
! MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
! PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);
! memcpy(frame->data, frame->rawdata, frame->bytes_recvd);
! } else {
! switch (frame->format) {
! case VIDEO_PALETTE_GREY:
! ov51x_postprocess_grey(ov, frame);
! break;
! case VIDEO_PALETTE_YUV420:
! case VIDEO_PALETTE_YUV420P:
! case VIDEO_PALETTE_RGB565:
! case VIDEO_PALETTE_RGB24:
! case VIDEO_PALETTE_YUV422:
! case VIDEO_PALETTE_YUYV:
! case VIDEO_PALETTE_YUV422P:
! ov51x_postprocess_yuv420(ov, frame);
! break;
! default:
! err("Cannot convert data to %s",
! symbolic(v4l1_plist, frame->format));
! }
}
}
/**********************************************************************
*
! * OV51x data transfer, IRQ handler
*
**********************************************************************/
! static inline void
! ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
{
! int num, offset;
! int pnum = in[ov->packet_size - 1]; /* Get packet number */
! int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
! struct ov511_frame *frame = &ov->frame[ov->curframe];
! struct timeval *ts;
!
! /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
! * byte non-zero. The EOF packet has image width/height in the
! * 10th and 11th bytes. The 9th byte is given as follows:
! *
! * bit 7: EOF
! * 6: compression enabled
! * 5: 422/420/400 modes
! * 4: 422/420/400 modes
! * 3: 1
! * 2: snapshot button on
! * 1: snapshot frame
! * 0: even/odd field
! */
!
! if (printph) {
! info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
! pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
! in[7], in[8], in[9], in[10], in[11]);
! }
!
! /* Check for SOF/EOF packet */
! if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) ||
! (~in[8] & 0x08))
! goto check_middle;
!
! /* Frame end */
! if (in[8] & 0x80) {
! ts = (struct timeval *)(frame->data
! + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
! do_gettimeofday(ts);
!
! /* Get the actual frame size from the EOF header */
! frame->rawwidth = ((int)(in[9]) + 1) * 8;
! frame->rawheight = ((int)(in[10]) + 1) * 8;
!
! PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
! ov->curframe, pnum, frame->rawwidth, frame->rawheight,
! frame->bytes_recvd);
!
! /* Validate the header data */
! RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
! RESTRICT_TO_RANGE(frame->rawheight, ov->minheight,
! ov->maxheight);
!
! /* Don't allow byte count to exceed buffer size */
! RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
!
! if (frame->scanstate == STATE_LINES) {
! int nextf;
!
! frame->grabstate = FRAME_DONE; // FIXME: Is this right?
!
! if (waitqueue_active(&frame->wq)) {
! frame->grabstate = FRAME_DONE;
! wake_up_interruptible(&frame->wq);
! }
!
! /* If next frame is ready or grabbing,
! * point to it */
! nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
! if (ov->frame[nextf].grabstate == FRAME_READY
! || ov->frame[nextf].grabstate == FRAME_GRABBING) {
! ov->curframe = nextf;
! ov->frame[nextf].scanstate = STATE_SCANNING;
! } else {
! if (frame->grabstate == FRAME_DONE) {
! PDEBUG(4, "** Frame done **");
! } else {
! PDEBUG(4, "Frame not ready? state = %d",
! ov->frame[nextf].grabstate);
! }
!
! ov->curframe = -1;
! }
! } else {
! PDEBUG(5, "Frame done, but not scanning");
! }
! /* Image corruption caused by misplaced frame->segment = 0
! * fixed by carlosf@conectiva.com.br
! */
! } else {
! /* Frame start */
! PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
!
! /* Check to see if it's a snapshot frame */
! /* FIXME?? Should the snapshot reset go here? Performance? */
! if (in[8] & 0x02) {
! frame->snapshot = 1;
! PDEBUG(3, "snapshot detected");
! }
!
! frame->scanstate = STATE_LINES;
! frame->bytes_recvd = 0;
! frame->compressed = in[8] & 0x40;
! }
!
! check_middle:
! /* Are we in a frame? */
! if (frame->scanstate != STATE_LINES) {
! PDEBUG(5, "Not in a frame; packet skipped");
! return;
! }
!
! /* If frame start, skip header */
! if (frame->bytes_recvd == 0)
! offset = 9;
! else
! offset = 0;
!
! num = n - offset - 1;
! /* Dump all data exactly as received */
! if (dumppix == 2) {
! frame->bytes_recvd += n - 1;
! if (frame->bytes_recvd <= max_raw)
! memcpy(frame->rawdata + frame->bytes_recvd - (n - 1),
! in, n - 1);
! else
! PDEBUG(3, "Raw data buffer overrun!! (%d)",
! frame->bytes_recvd - max_raw);
! } else if (!frame->compressed && !remove_zeros) {
! frame->bytes_recvd += num;
! if (frame->bytes_recvd <= max_raw)
! memcpy(frame->rawdata + frame->bytes_recvd - num,
! in + offset, num);
! else
! PDEBUG(3, "Raw data buffer overrun!! (%d)",
! frame->bytes_recvd - max_raw);
! } else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */
! int b, read = 0, allzero, copied = 0;
! if (offset) {
! frame->bytes_recvd += 32 - offset; // Bytes out
! memcpy(frame->rawdata, in + offset, 32 - offset);
! read += 32;
! }
! while (read < n - 1) {
! allzero = 1;
! for (b = 0; b < 32; b++) {
! if (in[read + b]) {
! allzero = 0;
! break;
! }
! }
! if (allzero) {
! /* Don't copy it */
! } else {
! if (frame->bytes_recvd + copied + 32 <= max_raw)
! {
! memcpy(frame->rawdata
! + frame->bytes_recvd + copied,
! in + read, 32);
! copied += 32;
! } else {
! PDEBUG(3, "Raw data buffer overrun!!");
! }
! }
! read += 32;
! }
! frame->bytes_recvd += copied;
! }
! }
! static inline void
! ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
! {
! int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
! struct ov511_frame *frame = &ov->frame[ov->curframe];
! struct timeval *ts;
!
! /* Don't copy the packet number byte */
! if (ov->packet_numbering)
! --n;
!
! /* A false positive here is likely, until OVT gives me
! * the definitive SOF/EOF format */
! if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) {
! if (printph) {
! info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0],
! in[1], in[2], in[3], in[4], in[5], in[6], in[7]);
! }
!
! if (frame->scanstate == STATE_LINES) {
! PDEBUG(4, "Detected frame end/start");
! goto eof;
! } else { //scanstate == STATE_SCANNING
! /* Frame start */
! PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
! goto sof;
! }
! } else {
! goto check_middle;
! }
! eof:
! ts = (struct timeval *)(frame->data
! + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
! do_gettimeofday(ts);
! PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d",
! ov->curframe,
! (int)(in[9]), (int)(in[10]), frame->bytes_recvd);
! // FIXME: Since we don't know the header formats yet,
! // there is no way to know what the actual image size is
! frame->rawwidth = frame->width;
! frame->rawheight = frame->height;
! /* Validate the header data */
! RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
! RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
! /* Don't allow byte count to exceed buffer size */
! RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
! if (frame->scanstate == STATE_LINES) {
! int nextf;
! frame->grabstate = FRAME_DONE; // FIXME: Is this right?
! if (waitqueue_active(&frame->wq)) {
! frame->grabstate = FRAME_DONE;
! wake_up_interruptible(&frame->wq);
! }
! /* If next frame is ready or grabbing,
! * point to it */
! nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
! if (ov->frame[nextf].grabstate == FRAME_READY
! || ov->frame[nextf].grabstate == FRAME_GRABBING) {
! ov->curframe = nextf;
! ov->frame[nextf].scanstate = STATE_SCANNING;
! frame = &ov->frame[nextf];
! } else {
! if (frame->grabstate == FRAME_DONE) {
! PDEBUG(4, "** Frame done **");
! } else {
! PDEBUG(4, "Frame not ready? state = %d",
! ov->frame[nextf].grabstate);
}
- ov->curframe = -1;
- PDEBUG(4, "SOF dropped (no active frame)");
- return; /* Nowhere to store this frame */
- }
- }
- sof:
- PDEBUG(4, "Starting capture on frame %d", frame->framenum);
-
- // Snapshot not reverse-engineered yet.
#if 0
! /* Check to see if it's a snapshot frame */
! /* FIXME?? Should the snapshot reset go here? Performance? */
! if (in[8] & 0x02) {
! frame->snapshot = 1;
! PDEBUG(3, "snapshot detected");
! }
#endif
! frame->scanstate = STATE_LINES;
! frame->bytes_recvd = 0;
! frame->compressed = 1;
! check_middle:
! /* Are we in a frame? */
! if (frame->scanstate != STATE_LINES) {
! PDEBUG(4, "scanstate: no SOF yet");
! return;
! }
! /* Dump all data exactly as received */
! if (dumppix == 2) {
! frame->bytes_recvd += n;
! if (frame->bytes_recvd <= max_raw)
! memcpy(frame->rawdata + frame->bytes_recvd - n, in, n);
! else
! PDEBUG(3, "Raw data buffer overrun!! (%d)",
! frame->bytes_recvd - max_raw);
! } else {
! /* All incoming data are divided into 8-byte segments. If the
! * segment contains all zero bytes, it must be skipped. These
! * zero-segments allow the OV518 to mainain a constant data rate
! * regardless of the effectiveness of the compression. Segments
! * are aligned relative to the beginning of each isochronous
! * packet. The first segment in each image is a header (the
! * decompressor skips it later).
! */
! int b, read = 0, allzero, copied = 0;
! while (read < n) {
! allzero = 1;
! for (b = 0; b < 8; b++) {
! if (in[read + b]) {
! allzero = 0;
break;
- }
- }
! if (allzero) {
! /* Don't copy it */
! } else {
! if (frame->bytes_recvd + copied + 8 <= max_raw)
! {
! memcpy(frame->rawdata
! + frame->bytes_recvd + copied,
! in + read, 8);
! copied += 8;
! } else {
! PDEBUG(3, "Raw data buffer overrun!!");
! }
}
! read += 8;
}
- frame->bytes_recvd += copied;
}
}
! static void
! ov51x_isoc_irq(struct urb *urb)
{
! int i;
! struct usb_ov511 *ov;
struct ov511_sbuf *sbuf;
if (!urb->context) {
--- 1248,1863 ----
* this data is scrambled.
*/
! #define HDIV 8
! #define WDIV (256/HDIV)
!
static void
! ov511_parse_gbr422_to_rgb24(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iOutUV, int iHalf, int iWidth)
{
! int k, l, m;
! unsigned char *pIn;
! unsigned char *pOut, *pOut1;
pIn = pIn0;
! pOut = pOut0 + iOutUV + (force_rgb ? 2 : 0);
!
! for (k = 0; k < 8; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =
! *(pOut1 + iWidth*3 + 3) = *pIn++;
! pOut1 += 6;
}
! pOut += iWidth*3*2;
! }
!
! pIn = pIn0 + 64;
! pOut = pOut0 + iOutUV + (force_rgb ? 0 : 2);
! for (k = 0; k < 8; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =
! *(pOut1 + iWidth*3 + 3) = *pIn++;
! pOut1 += 6;
! }
! pOut += iWidth*3*2;
}
pIn = pIn0 + 128;
! pOut = pOut0 + iOutY + 1;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! for (m = 0; m < 8; m++) {
! *pOut1 = *pIn++;
! pOut1 += 3;
}
+ pOut1 += (iWidth - 8) * 3;
}
! pOut += 8 * 3;
}
}
static void
! ov511_parse_yuv420_to_rgb(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iOutUV, int iHalf, int iWidth, int bits)
{
! int k, l, m;
! int bytes = bits >> 3;
! unsigned char *pIn;
! unsigned char *pOut, *pOut1;
! /* Just copy the Y's if in the first stripe */
! if (!iHalf) {
! pIn = pIn0 + 128;
! pOut = pOut0 + iOutY;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! for (m = 0; m < 8; m++) {
! *pOut1 = *pIn++;
! pOut1 += bytes;
! }
! pOut1 += (iWidth - 8) * bytes;
! }
! pOut += 8 * bytes;
! }
}
! /* Use the first half of VUs to calculate value */
! pIn = pIn0;
! pOut = pOut0 + iOutUV;
! for (l = 0; l < 4; l++) {
! for (m=0; m<8; m++) {
! int y00 = *(pOut);
! int y01 = *(pOut+bytes);
! int y10 = *(pOut+iWidth*bytes);
! int y11 = *(pOut+iWidth*bytes+bytes);
! int v = *(pIn+64) - 128;
! int u = *pIn++ - 128;
! ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,
! pOut, bits);
! pOut += 2 * bytes;
}
! pOut += (iWidth*2 - 16) * bytes;
}
! /* Just copy the other UV rows */
! for (l = 0; l < 4; l++) {
! for (m = 0; m < 8; m++) {
! *pOut++ = *(pIn + 64);
! *pOut = *pIn++;
! pOut += 2 * bytes - 1;
! }
! pOut += (iWidth*2 - 16) * bytes;
! }
!
! /* Calculate values if it's the second half */
! if (iHalf) {
! pIn = pIn0 + 128;
! pOut = pOut0 + iOutY;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l=0; l<4; l++) {
! for (m=0; m<4; m++) {
! int y10 = *(pIn+8);
! int y00 = *pIn++;
! int y11 = *(pIn+8);
! int y01 = *pIn++;
! int v = *pOut1 - 128;
! int u = *(pOut1+1) - 128;
! ov511_move_420_block(y00, y01, y10,
! y11, u, v, iWidth, pOut1, bits);
! pOut1 += 2 * bytes;
! }
! pOut1 += (iWidth*2 - 8) * bytes;
! pIn += 8;
! }
! pOut += 8 * bytes;
}
}
}
static void
! ov511_dumppix(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iOutUV, int iHalf, int iWidth)
{
! int i, j, k;
! unsigned char *pIn, *pOut, *pOut1;
! switch (dumppix) {
! case 1: /* Just dump YUV data straight out for debug */
! pOut0 += iOutY;
! for (i = 0; i < HDIV; i++) {
! for (j = 0; j < WDIV; j++) {
! *pOut0++ = *pIn0++;
! *pOut0++ = *pIn0++;
! *pOut0++ = *pIn0++;
! }
! pOut0 += (iWidth - WDIV) * 3;
! }
! break;
! case 2: /* This converts the Y data to "black-and-white" RGB data */
! /* Useful for experimenting with compression */
! pIn = pIn0 + 128;
! pOut = pOut0 + iOutY;
! for (i = 0; i < 4; i++) {
! pOut1 = pOut;
! for (j = 0; j < 8; j++) {
! for (k = 0; k < 8; k++) {
! *pOut1++ = *pIn;
! *pOut1++ = *pIn;
! *pOut1++ = *pIn++;
! }
! pOut1 += (iWidth - 8) * 3;
! }
! pOut += 8 * 3;
! }
! break;
! case 3: /* This will dump only the Y channel data stream as-is */
! pIn = pIn0 + 128;
! pOut = pOut0 + output_offset;
! for (i = 0; i < 256; i++) {
! *pOut++ = *pIn;
! *pOut++ = *pIn;
! *pOut++ = *pIn++;
! output_offset += 3;
! }
! break;
! } /* End switch (dumppix) */
}
! /* This converts YUV420 segments to YUYV */
static void
! ov511_parse_data_yuv422(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iOutUV, int iWidth)
{
! int k, l, m;
! unsigned char *pIn, *pOut, *pOut1;
! pIn = pIn0 + 128;
! pOut = pOut0 + iOutY;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! for (m = 0; m < 8; m++) {
! *pOut1 = (*pIn++);
! pOut1 += 2;
! }
! pOut1 += (iWidth - 8) * 2;
}
! pOut += 8 * 2;
}
+ pIn = pIn0;
+ pOut = pOut0 + iOutUV + 1;
+ for (l = 0; l < 8; l++) {
+ for (m=0; m<8; m++) {
+ int v = *(pIn+64);
+ int u = *pIn++;
+
*pOut = u;
*(pOut+2) = v;
! *(pOut+iWidth) = u;
! *(pOut+iWidth+2) = v;
pOut += 4;
}
! pOut += (iWidth*4 - 32);
}
}
static void
! ov511_parse_data_yuv420(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iOutUV, int iWidth, int iHeight)
{
! int k, l, m;
! unsigned char *pIn;
! unsigned char *pOut, *pOut1;
! unsigned a = iWidth * iHeight;
! unsigned w = iWidth / 2;
!
! pIn = pIn0;
! pOut = pOut0 + iOutUV + a;
! for (k = 0; k < 8; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) *pOut1++ = *pIn++;
! pOut += w;
! }
!
! pIn = pIn0 + 64;
! pOut = pOut0 + iOutUV + a + a/4;
! for (k = 0; k < 8; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) *pOut1++ = *pIn++;
pOut += w;
}
! pIn = pIn0 + 128;
! pOut = pOut0 + iOutY;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! for (m = 0; m < 8; m++)
! *pOut1++ =*pIn++;
! pOut1 += iWidth - 8;
! }
! pOut += 8;
}
}
static void
! ov511_parse_data_yuv422p(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iOutUV, int iWidth, int iHeight)
{
! int k, l, m;
! unsigned char *pIn;
! unsigned char *pOut, *pOut1;
! unsigned a = iWidth * iHeight;
! unsigned w = iWidth / 2;
! pIn = pIn0;
! pOut = pOut0 + iOutUV + a;
! for (k = 0; k < 8; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! *pOut1 = *(pOut1 + w) = *pIn++;
! pOut1++;
! }
! pOut += iWidth;
}
! pIn = pIn0 + 64;
! pOut = pOut0 + iOutUV + a + a/2;
! for (k = 0; k < 8; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! *pOut1 = *(pOut1 + w) = *pIn++;
! pOut1++;
}
! pOut += iWidth;
}
! pIn = pIn0 + 128;
! pOut = pOut0 + iOutY;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! for (m = 0; m < 8; m++)
! *pOut1++ =*pIn++;
! pOut1 += iWidth - 8;
}
+ pOut += 8;
}
}
+ /*
+ * For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
+ * The segments represent 4 squares of 8x8 pixels as follows:
+ *
+ * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199
+ * 8 9 ... 15 72 73 ... 79 200 201 ... 207
+ * ... ... ...
+ * 56 57 ... 63 120 121 ... 127 248 249 ... 255
+ *
+ */
static void
! ov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0,
! int iOutY, int iWidth)
{
! int k, l, m;
! unsigned char *pIn;
! unsigned char *pOut, *pOut1;
! pIn = pIn0;
! pOut = pOut0 + iOutY;
! for (k = 0; k < 4; k++) {
! pOut1 = pOut;
! for (l = 0; l < 8; l++) {
! for (m = 0; m < 8; m++) {
! *pOut1++ = *pIn++;
! }
! pOut1 += iWidth - 8;
}
+ pOut += 8;
+ }
}
! /*
! * fixFrameRGBoffset--
! * My camera seems to return the red channel about 1 pixel
! * low, and the blue channel about 1 pixel high. After YUV->RGB
! * conversion, we can correct this easily. OSL 2/24/2000.
*/
! static void fixFrameRGBoffset(struct ov511_frame *frame)
{
! int x, y;
! int rowBytes = frame->width*3, w = frame->width;
! unsigned char *rgb = frame->data;
! const int shift = 1; /* Distance to shift pixels by, vertically */
! /* Don't bother with little images */
! if (frame->width < 400)
! return;
! /* Shift red channel up */
! for (y = shift; y < frame->height; y++) {
! int lp = (y-shift)*rowBytes; /* Previous line offset */
! int lc = y*rowBytes; /* Current line offset */
! for (x = 0; x < w; x++)
! rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
}
! /* Shift blue channel down */
! for (y = frame->height-shift-1; y >= 0; y--) {
! int ln = (y + shift) * rowBytes; /* Next line offset */
! int lc = y * rowBytes; /* Current line offset */
! for (x = 0; x < w; x++)
! rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
}
}
/**********************************************************************
*
! * OV511 data transfer, IRQ handler
*
**********************************************************************/
! static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
{
! unsigned char *cdata;
! int i, totlen = 0;
! int aPackNum[10];
! struct ov511_frame *frame;
! unsigned char *pData;
! int iPix;
! PDEBUG (4, "Moving %d packets", urb->number_of_packets);
! for (i = 0; i < urb->number_of_packets; i++) {
! int n = urb->iso_frame_desc[i].actual_length;
! int st = urb->iso_frame_desc[i].status;
! urb->iso_frame_desc[i].actual_length = 0;
! urb->iso_frame_desc[i].status = 0;
! cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
! aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1;
! if (!n || ov511->curframe == -1)
! continue;
! if (st)
! PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
! frame = &ov511->frame[ov511->curframe];
!
! /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
! * byte non-zero. The EOF packet has image width/height in the
! * 10th and 11th packets. The 9th bit is given as follows:
! *
! * bit 7: EOF
! * 6: compression enabled
! * 5: 422/420/400 modes
! * 4: 422/420/400 modes
! * 3: 1
! * 2: snapshot bottom on
! * 1: snapshot frame
! * 0: even/odd field
! */
! /* Check for SOF/EOF packet */
! if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] |
! cdata[4] | cdata[5] | cdata[6] | cdata[7]) ||
! (~cdata[8] & 0x08))
! goto check_middle;
!
! /* Frame end */
! if (cdata[8] & 0x80) {
! struct timeval *ts;
!
! ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);
! do_gettimeofday (ts);
!
! PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d",
! ov511->curframe, (int)(cdata[ov511->packet_size - 1]),
! (int)(cdata[9]), (int)(cdata[10]));
! if (frame->scanstate == STATE_LINES) {
! int iFrameNext;
! if (fix_rgb_offset)
! fixFrameRGBoffset(frame);
! frame->grabstate = FRAME_DONE;
! if (waitqueue_active(&frame->wq)) {
! frame->grabstate = FRAME_DONE;
! wake_up_interruptible(&frame->wq);
! }
! /* If next frame is ready or grabbing,
! * point to it */
! iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
! if (ov511->frame[iFrameNext].grabstate == FRAME_READY
! || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) {
! ov511->curframe = iFrameNext;
! ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
! } else {
! if (frame->grabstate == FRAME_DONE) {
! PDEBUG(4, "Frame done! congratulations");
! } else {
! PDEBUG(4, "Frame not ready? state = %d",
! ov511->frame[iFrameNext].grabstate);
! }
! ov511->curframe = -1;
! }
}
+ /* Image corruption caused by misplaced frame->segment = 0
+ * fixed by carlosf@conectiva.com.br
+ */
+ } else {
+ /* Frame start */
+ PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
#if 0
! /* Make sure no previous data carries over; necessary
! * for compression experimentation */
! memset(frame->data, 0, MAX_DATA_SIZE);
#endif
! output_offset = 0;
! /* Check to see if it's a snapshot frame */
! /* FIXME?? Should the snapshot reset go here? Performance? */
! if (cdata[8] & 0x02) {
! frame->snapshot = 1;
! PDEBUG(3, "snapshot detected");
! }
! frame->scanstate = STATE_LINES;
! frame->segment = 0;
! }
!
! check_middle:
! /* Are we in a frame? */
! if (frame->scanstate != STATE_LINES)
! continue;
! /* Deal with leftover from last segment, if any */
! if (frame->segment) {
! pData = ov511->scratch;
! iPix = -ov511->scratchlen;
! memmove(pData + ov511->scratchlen, cdata,
! iPix+frame->segsize);
! } else {
! pData = &cdata[iPix = 9];
! }
! /* Parse the segments */
! while (iPix <= (ov511->packet_size - 1) - frame->segsize &&
! frame->segment < frame->width * frame->height / 256) {
! int iSegY, iSegUV;
! int iY, jY, iUV, jUV;
! int iOutY, iOutYP, iOutUV, iOutUVP;
! unsigned char *pOut;
!
! iSegY = iSegUV = frame->segment;
! pOut = frame->data;
! frame->segment++;
! iPix += frame->segsize;
!
! /* Handle subwindow */
! if (frame->sub_flag) {
! int iSeg1;
!
! iSeg1 = iSegY / (ov511->subw / 32);
! iSeg1 *= frame->width / 32;
! iSegY = iSeg1 + (iSegY % (ov511->subw / 32));
! if (iSegY >= frame->width * ov511->subh / 256)
break;
! iSeg1 = iSegUV / (ov511->subw / 16);
! iSeg1 *= frame->width / 16;
! iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));
!
! pOut += (ov511->subx + ov511->suby * frame->width) *
! (frame->depth >> 3);
! }
!
! /*
! * i counts segment lines
! * j counts segment columns
! * iOut is the offset (in bytes) of the upper left corner
! */
! iY = iSegY / (frame->width / WDIV);
! jY = iSegY - iY * (frame->width / WDIV);
! iOutYP = iY*HDIV*frame->width + jY*WDIV;
! iOutY = iOutYP * (frame->depth >> 3);
! iUV = iSegUV / (frame->width / WDIV * 2);
! jUV = iSegUV - iUV * (frame->width / WDIV * 2);
! iOutUVP = iUV*HDIV*2*frame->width + jUV*WDIV/2;
! iOutUV = iOutUVP * (frame->depth >> 3);
!
! switch (frame->format) {
! case VIDEO_PALETTE_GREY:
! ov511_parse_data_grey (pData, pOut, iOutY, frame->width);
! break;
! case VIDEO_PALETTE_RGB24:
! if (dumppix)
! ov511_dumppix(pData, pOut, iOutY, iOutUV,
! iY & 1, frame->width);
! else if (sensor_gbr)
! ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV,
! iY & 1, frame->width);
! else
! ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
! iY & 1, frame->width, 24);
! break;
! case VIDEO_PALETTE_RGB565:
! ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
! iY & 1, frame->width, 16);
! break;
! case VIDEO_PALETTE_YUV422:
! case VIDEO_PALETTE_YUYV:
! ov511_parse_data_yuv422(pData, pOut, iOutY, iOutUV, frame->width);
! break;
! case VIDEO_PALETTE_YUV420:
! ov511_parse_data_yuv420 (pData, pOut, iOutYP, iUV*HDIV*frame->width/2 + jUV*WDIV/4,
! frame->width, frame->height);
! break;
! case VIDEO_PALETTE_YUV422P:
! ov511_parse_data_yuv422p (pData, pOut, iOutYP, iOutUVP/2,
! frame->width, frame->height);
! break;
! default:
! err("Unsupported format: %d", frame->format);
}
!
! pData = &cdata[iPix];
! }
!
! /* Save extra data for next time */
! if (frame->segment < frame->width * frame->height / 256) {
! ov511->scratchlen = (ov511->packet_size - 1) - iPix;
! if (ov511->scratchlen < frame->segsize)
! memmove(ov511->scratch, pData, ov511->scratchlen);
! else
! ov511->scratchlen = 0;
}
}
+
+ PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d",
+ aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
+ aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
+
+ return totlen;
}
! static void ov511_isoc_irq(struct urb *urb)
{
! int len;
! struct usb_ov511 *ov511;
struct ov511_sbuf *sbuf;
if (!urb->context) {
***************
*** 4084,4330 ****
return;
}
! sbuf = urb->context;
! ov = sbuf->ov;
! if (!ov || !ov->dev || !ov->user) {
PDEBUG(4, "no device, or not open");
return;
}
! if (!ov->streaming) {
PDEBUG(4, "hmmm... not streaming, but got interrupt");
return;
}
! if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
! PDEBUG(4, "URB unlinked");
! return;
! }
!
! if (urb->status != -EINPROGRESS && urb->status != 0) {
! err("ERROR: urb->status=%d: %s", urb->status,
! symbolic(urb_errlist, urb->status));
}
! /* Copy the data received into our frame buffer */
! PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n,
! urb->number_of_packets);
! for (i = 0; i < urb->number_of_packets; i++) {
! /* Warning: Don't call *_move_data() if no frame active! */
! if (ov->curframe >= 0) {
! int n = urb->iso_frame_desc[i].actual_length;
! int st = urb->iso_frame_desc[i].status;
! unsigned char *cdata;
!
! urb->iso_frame_desc[i].actual_length = 0;
! urb->iso_frame_desc[i].status = 0;
!
! cdata = urb->transfer_buffer
! + urb->iso_frame_desc[i].offset;
!
! if (!n) {
! PDEBUG(4, "Zero-length packet");
! continue;
! }
!
! if (st)
! PDEBUG(2, "data error: [%d] len=%d, status=%d",
! i, n, st);
!
! if (ov->bclass == BCL_OV511)
! ov511_move_data(ov, cdata, n);
! else if (ov->bclass == BCL_OV518)
! ov518_move_data(ov, cdata, n);
! else
! err("Unknown bridge device (%d)", ov->bridge);
! } else if (waitqueue_active(&ov->wq)) {
! wake_up_interruptible(&ov->wq);
! }
! }
!
! urb->dev = ov->dev;
return;
}
! /****************************************************************************
! *
! * Stream initialization and termination
! *
! ***************************************************************************/
!
! static int
! ov51x_init_isoc(struct usb_ov511 *ov)
{
! struct urb *urb;
int fx, err, n, size;
PDEBUG(3, "*** Initializing capture ***");
! ov->curframe = -1;
!
! if (ov->bridge == BRG_OV511) {
! if (cams == 1) size = 993;
! else if (cams == 2) size = 513;
! else if (cams == 3 || cams == 4) size = 257;
! else {
! err("\"cams\" parameter too high!");
! return -1;
! }
! } else if (ov->bridge == BRG_OV511PLUS) {
! if (cams == 1) size = 961;
! else if (cams == 2) size = 513;
! else if (cams == 3 || cams == 4) size = 257;
! else if (cams >= 5 && cams <= 8) size = 129;
! else if (cams >= 9 && cams <= 31) size = 33;
else {
err("\"cams\" parameter too high!");
return -1;
}
! } else if (ov->bclass == BCL_OV518) {
! if (cams == 1) size = 896;
! else if (cams == 2) size = 512;
! else if (cams == 3 || cams == 4) size = 256;
! else if (cams >= 5 && cams <= 8) size = 128;
else {
err("\"cams\" parameter too high!");
return -1;
}
! } else {
err("invalid bridge type");
return -1;
}
! // FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now
! if (ov->bclass == BCL_OV518) {
! if (packetsize == -1) {
! ov518_set_packet_size(ov, 640);
! } else {
! info("Forcing packet size to %d", packetsize);
! ov518_set_packet_size(ov, packetsize);
! }
! } else {
! if (packetsize == -1) {
! ov511_set_packet_size(ov, size);
! } else {
! info("Forcing packet size to %d", packetsize);
! ov511_set_packet_size(ov, packetsize);
! }
! }
for (n = 0; n < OV511_NUMSBUF; n++) {
urb = usb_alloc_urb(FRAMES_PER_DESC);
if (!urb) {
err("init isoc: usb_alloc_urb ret. NULL");
return -ENOMEM;
}
! ov->sbuf[n].urb = urb;
! urb->dev = ov->dev;
! urb->context = &ov->sbuf[n];
! urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS);
urb->transfer_flags = USB_ISO_ASAP;
! urb->transfer_buffer = ov->sbuf[n].data;
! urb->complete = ov51x_isoc_irq;
urb->number_of_packets = FRAMES_PER_DESC;
! urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
! urb->iso_frame_desc[fx].offset = ov->packet_size * fx;
! urb->iso_frame_desc[fx].length = ov->packet_size;
}
}
! ov->streaming = 1;
!
! ov->sbuf[OV511_NUMSBUF - 1].urb->next = ov->sbuf[0].urb;
for (n = 0; n < OV511_NUMSBUF - 1; n++)
! ov->sbuf[n].urb->next = ov->sbuf[n+1].urb;
for (n = 0; n < OV511_NUMSBUF; n++) {
! ov->sbuf[n].urb->dev = ov->dev;
! err = usb_submit_urb(ov->sbuf[n].urb);
! if (err) {
err("init isoc: usb_submit_urb(%d) ret %d", n, err);
- return err;
- }
}
return 0;
}
! static void
! ov51x_unlink_isoc(struct usb_ov511 *ov)
{
int n;
! /* Unschedule all of the iso td's */
! for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
! if (ov->sbuf[n].urb) {
! usb_unlink_urb(ov->sbuf[n].urb);
! usb_free_urb(ov->sbuf[n].urb);
! ov->sbuf[n].urb = NULL;
! }
! }
! }
!
! static void
! ov51x_stop_isoc(struct usb_ov511 *ov)
! {
! if (!ov->streaming || !ov->dev)
return;
! PDEBUG(3, "*** Stopping capture ***");
! if (ov->bclass == BCL_OV518)
! ov518_set_packet_size(ov, 0);
! else
! ov511_set_packet_size(ov, 0);
! ov->streaming = 0;
! ov51x_unlink_isoc(ov);
}
! static int
! ov51x_new_frame(struct usb_ov511 *ov, int framenum)
{
struct ov511_frame *frame;
- int newnum;
-
- PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);
! if (!ov->dev)
return -1;
/* If we're not grabbing a frame right now and the other frame is */
/* ready to be grabbed into, then use it instead */
! if (ov->curframe == -1) {
! newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
! if (ov->frame[newnum].grabstate == FRAME_READY)
! framenum = newnum;
} else
return 0;
! frame = &ov->frame[framenum];
! PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum,
! frame->width, frame->height);
frame->grabstate = FRAME_GRABBING;
frame->scanstate = STATE_SCANNING;
frame->snapshot = 0;
! ov->curframe = framenum;
/* Make sure it's not too big */
! if (frame->width > ov->maxwidth)
! frame->width = ov->maxwidth;
frame->width &= ~7L; /* Multiple of 8 */
! if (frame->height > ov->maxheight)
! frame->height = ov->maxheight;
frame->height &= ~3L; /* Multiple of 4 */
--- 1865,2035 ----
return;
}
! ov511 = (struct usb_ov511 *) urb->context;
! if (!ov511->dev || !ov511->user) {
PDEBUG(4, "no device, or not open");
return;
}
! if (!ov511->streaming) {
PDEBUG(4, "hmmm... not streaming, but got interrupt");
return;
}
+
+ sbuf = &ov511->sbuf[ov511->cursbuf];
! /* Copy the data received into our scratch buffer */
! if (ov511->curframe >= 0) {
! len = ov511_move_data(ov511, urb);
! } else if (waitqueue_active(&ov511->wq)) {
! wake_up_interruptible(&ov511->wq);
}
! /* Move to the next sbuf */
! ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
! urb->dev = ov511->dev;
return;
}
! static int ov511_init_isoc(struct usb_ov511 *ov511)
{
! urb_t *urb;
int fx, err, n, size;
PDEBUG(3, "*** Initializing capture ***");
! ov511->compress = 0;
! ov511->curframe = -1;
! ov511->cursbuf = 0;
! ov511->scratchlen = 0;
!
! if (ov511->bridge == BRG_OV511)
! if (cams == 1) size = 993;
! else if (cams == 2) size = 513;
! else if (cams == 3 || cams == 4) size = 257;
else {
err("\"cams\" parameter too high!");
return -1;
}
! else if (ov511->bridge == BRG_OV511PLUS)
! if (cams == 1) size = 961;
! else if (cams == 2) size = 513;
! else if (cams == 3 || cams == 4) size = 257;
! else if (cams >= 5 && cams <= 8) size = 129;
! else if (cams >= 9 && cams <= 31) size = 33;
else {
err("\"cams\" parameter too high!");
return -1;
}
! else {
err("invalid bridge type");
return -1;
}
! ov511_set_packet_size(ov511, size);
for (n = 0; n < OV511_NUMSBUF; n++) {
urb = usb_alloc_urb(FRAMES_PER_DESC);
+
if (!urb) {
err("init isoc: usb_alloc_urb ret. NULL");
return -ENOMEM;
}
! ov511->sbuf[n].urb = urb;
! urb->dev = ov511->dev;
! urb->context = ov511;
! urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
urb->transfer_flags = USB_ISO_ASAP;
! urb->transfer_buffer = ov511->sbuf[n].data;
! urb->complete = ov511_isoc_irq;
urb->number_of_packets = FRAMES_PER_DESC;
! urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
! urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
! urb->iso_frame_desc[fx].length = ov511->packet_size;
}
}
! ov511->sbuf[OV511_NUMSBUF - 1].urb->next = ov511->sbuf[0].urb;
for (n = 0; n < OV511_NUMSBUF - 1; n++)
! ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb;
for (n = 0; n < OV511_NUMSBUF; n++) {
! ov511->sbuf[n].urb->dev = ov511->dev;
! err = usb_submit_urb(ov511->sbuf[n].urb);
! if (err)
err("init isoc: usb_submit_urb(%d) ret %d", n, err);
}
+ ov511->streaming = 1;
+
return 0;
}
! static void ov511_stop_isoc(struct usb_ov511 *ov511)
{
int n;
! if (!ov511->streaming || !ov511->dev)
return;
! PDEBUG (3, "*** Stopping capture ***");
! ov511_set_packet_size(ov511, 0);
! ov511->streaming = 0;
! /* Unschedule all of the iso td's */
! for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
! if (ov511->sbuf[n].urb) {
! ov511->sbuf[n].urb->next = NULL;
! usb_unlink_urb(ov511->sbuf[n].urb);
! usb_free_urb(ov511->sbuf[n].urb);
! ov511->sbuf[n].urb = NULL;
! }
! }
}
! static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
{
struct ov511_frame *frame;
! PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,
! framenum);
! if (!ov511->dev)
return -1;
/* If we're not grabbing a frame right now and the other frame is */
/* ready to be grabbed into, then use it instead */
! if (ov511->curframe == -1) {
! if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES].grabstate == FRAME_READY)
! framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
} else
return 0;
! frame = &ov511->frame[framenum];
! PDEBUG (4, "framenum = %d, width = %d, height = %d", framenum,
! frame->width, frame->height);
frame->grabstate = FRAME_GRABBING;
frame->scanstate = STATE_SCANNING;
+ frame->scanlength = 0; /* accumulated in ov511_parse_data() */
frame->snapshot = 0;
! ov511->curframe = framenum;
/* Make sure it's not too big */
! if (frame->width > ov511->maxwidth)
! frame->width = ov511->maxwidth;
frame->width &= ~7L; /* Multiple of 8 */
! if (frame->height > ov511->maxheight)
! frame->height = ov511->maxheight;
frame->height &= ~3L; /* Multiple of 4 */
***************
*** 4336,4956 ****
* Buffer management
*
***************************************************************************/
!
! /*
! * - You must acquire buf_lock before entering this function.
! * - Because this code will free any non-null pointer, you must be sure to null
! * them if you explicitly free them somewhere else!
! */
! static void
! ov51x_do_dealloc(struct usb_ov511 *ov)
{
int i;
- PDEBUG(4, "entered");
! if (ov->fbuf) {
! rvfree(ov->fbuf, OV511_NUMFRAMES
! * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
! ov->fbuf = NULL;
! }
! if (ov->rawfbuf) {
! vfree(ov->rawfbuf);
! ov->rawfbuf = NULL;
}
! if (ov->tempfbuf) {
! vfree(ov->tempfbuf);
! ov->tempfbuf = NULL;
! }
! for (i = 0; i < OV511_NUMSBUF; i++) {
! if (ov->sbuf[i].data) {
! kfree(ov->sbuf[i].data);
! ov->sbuf[i].data = NULL;
! }
! }
for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].data = NULL;
! ov->frame[i].rawdata = NULL;
! ov->frame[i].tempdata = NULL;
! if (ov->frame[i].compbuf) {
! free_page((unsigned long) ov->frame[i].compbuf);
! ov->frame[i].compbuf = NULL;
}
}
!
! PDEBUG(4, "buffer memory deallocated");
! ov->buf_state = BUF_NOT_ALLOCATED;
PDEBUG(4, "leaving");
}
! static int
! ov51x_alloc(struct usb_ov511 *ov)
{
int i;
- const int w = ov->maxwidth;
- const int h = ov->maxheight;
- const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h);
- const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);
-
PDEBUG(4, "entered");
- down(&ov->buf_lock);
! if (ov->buf_state == BUF_PEND_DEALLOC) {
! ov->buf_state = BUF_ALLOCATED;
! del_timer(&ov->buf_timer);
}
! if (ov->buf_state == BUF_ALLOCATED)
! goto out;
! ov->fbuf = rvmalloc(data_bufsize);
! if (!ov->fbuf)
! goto error;
! ov->rawfbuf = vmalloc(raw_bufsize);
! if (!ov->rawfbuf)
! goto error;
! memset(ov->rawfbuf, 0, raw_bufsize);
! ov->tempfbuf = vmalloc(raw_bufsize);
! if (!ov->tempfbuf)
! goto error;
! memset(ov->tempfbuf, 0, raw_bufsize);
! for (i = 0; i < OV511_NUMSBUF; i++) {
! ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
! MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
! if (!ov->sbuf[i].data)
! goto error;
! PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data);
}
! for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h);
! ov->frame[i].rawdata = ov->rawfbuf
! + i * MAX_RAW_DATA_SIZE(w, h);
! ov->frame[i].tempdata = ov->tempfbuf
! + i * MAX_RAW_DATA_SIZE(w, h);
!
! ov->frame[i].compbuf =
! (unsigned char *) __get_free_page(GFP_KERNEL);
! if (!ov->frame[i].compbuf)
! goto error;
!
! PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data);
}
!
! ov->buf_state = BUF_ALLOCATED;
! out:
! up(&ov->buf_lock);
! PDEBUG(4, "leaving");
! return 0;
! error:
! ov51x_do_dealloc(ov);
! up(&ov->buf_lock);
! PDEBUG(4, "errored");
! return -ENOMEM;
! }
!
! static void
! ov51x_dealloc(struct usb_ov511 *ov, int now)
! {
! PDEBUG(4, "entered");
! down(&ov->buf_lock);
! ov51x_do_dealloc(ov);
! up(&ov->buf_lock);
PDEBUG(4, "leaving");
}
/****************************************************************************
*
! * V4L 1 API
*
***************************************************************************/
! static int
! ov51x_v4l1_open(struct video_device *vdev, int flags)
{
! struct usb_ov511 *ov = vdev->priv;
! int err, i;
PDEBUG(4, "opening");
!
! down(&ov->lock);
err = -EBUSY;
! if (ov->user)
goto out;
! err = ov51x_alloc(ov);
! if (err < 0)
goto out;
! ov->sub_flag = 0;
!
! /* In case app doesn't set them... */
! err = ov51x_set_default_params(ov);
! if (err < 0)
! goto out;
!
! /* Make sure frames are reset */
! for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].grabstate = FRAME_UNUSED;
! ov->frame[i].bytes_read = 0;
! }
!
! /* If compression is on, make sure now that a
! * decompressor can be loaded */
! if (ov->compress && !ov->decomp_ops) {
! err = request_decompressor(ov);
! if (err && !dumppix)
! goto out;
! }
! err = ov51x_init_isoc(ov);
if (err) {
! ov51x_dealloc(ov, 0);
goto out;
}
! ov->user++;
!
! if (ov->led_policy == LED_AUTO)
! ov51x_led_control(ov, 1);
out:
! up(&ov->lock);
return err;
}
! static void
! ov51x_v4l1_close(struct video_device *vdev)
{
! struct usb_ov511 *ov = vdev->priv;
PDEBUG(4, "ov511_close");
! down(&ov->lock);
!
! ov->user--;
! ov51x_stop_isoc(ov);
! release_decompressor(ov);
! if (ov->led_policy == LED_AUTO)
! ov51x_led_control(ov, 0);
!
! if (ov->dev)
! ov51x_dealloc(ov, 0);
! up(&ov->lock);
! /* Device unplugged while open. Only a minimum of unregistration is done
! * here; the disconnect callback already did the rest. */
! if (!ov->dev) {
! down(&ov->cbuf_lock);
! kfree(ov->cbuf);
! ov->cbuf = NULL;
! up(&ov->cbuf_lock);
! ov51x_dealloc(ov, 1);
! video_unregister_device(&ov->vdev);
! kfree(ov);
! ov = NULL;
! }
! return;
}
! /* Do not call this function directly! */
! static int
! ov51x_v4l1_ioctl_internal(struct usb_ov511 *ov, unsigned int cmd,
! void *arg)
{
! PDEBUG(5, "IOCtl: 0x%X", cmd);
! if (!ov->dev)
! return -EIO;
switch (cmd) {
case VIDIOCGCAP:
{
! struct video_capability *b = arg;
! PDEBUG(4, "VIDIOCGCAP");
! memset(b, 0, sizeof(struct video_capability));
! sprintf(b->name, "%s USB Camera",
! symbolic(brglist, ov->bridge));
! b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
! b->channels = ov->num_inputs;
! b->audios = 0;
! b->maxwidth = ov->maxwidth;
! b->maxheight = ov->maxheight;
! b->minwidth = ov->minwidth;
! b->minheight = ov->minheight;
return 0;
}
case VIDIOCGCHAN:
{
! struct video_channel *v = arg;
! PDEBUG(4, "VIDIOCGCHAN");
!
! if ((unsigned)(v->channel) >= ov->num_inputs) {
! err("Invalid channel (%d)", v->channel);
return -EINVAL;
- }
! v->norm = ov->norm;
! v->type = VIDEO_TYPE_CAMERA;
! v->flags = 0;
! // v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0;
! v->tuners = 0;
! decoder_get_input_name(ov, v->channel, v->name);
return 0;
}
case VIDIOCSCHAN:
{
! struct video_channel *v = arg;
! int err;
!
! PDEBUG(4, "VIDIOCSCHAN");
!
! /* Make sure it's not a camera */
! if (!ov->has_decoder) {
! if (v->channel == 0)
! return 0;
! else
! return -EINVAL;
! }
! if (v->norm != VIDEO_MODE_PAL &&
! v->norm != VIDEO_MODE_NTSC &&
! v->norm != VIDEO_MODE_SECAM &&
! v->norm != VIDEO_MODE_AUTO) {
! err("Invalid norm (%d)", v->norm);
! return -EINVAL;
! }
! if ((unsigned)(v->channel) >= ov->num_inputs) {
! err("Invalid channel (%d)", v->channel);
return -EINVAL;
- }
-
- err = decoder_set_input(ov, v->channel);
- if (err)
- return err;
-
- err = decoder_set_norm(ov, v->norm);
- if (err)
- return err;
return 0;
}
case VIDIOCGPICT:
{
! struct video_picture *p = arg;
! PDEBUG(4, "VIDIOCGPICT");
! memset(p, 0, sizeof(struct video_picture));
! if (sensor_get_picture(ov, p))
return -EIO;
return 0;
}
case VIDIOCSPICT:
{
! struct video_picture *p = arg;
int i;
! PDEBUG(4, "VIDIOCSPICT");
!
! if (!get_depth(p->palette))
! return -EINVAL;
! if (sensor_set_picture(ov, p))
! return -EIO;
! if (force_palette && p->palette != force_palette) {
! info("Palette rejected (%s)",
! symbolic(v4l1_plist, p->palette));
return -EINVAL;
! }
!
! // FIXME: Format should be independent of frames
! if (p->palette != ov->frame[0].format) {
! PDEBUG(4, "Detected format change");
!
! /* If we're collecting previous frame wait
! before changing modes */
! interruptible_sleep_on(&ov->wq);
! if (signal_pending(current)) return -EINTR;
!
! mode_init_regs(ov, ov->frame[0].width,
! ov->frame[0].height, p->palette, ov->sub_flag);
! }
!
! PDEBUG(4, "Setting depth=%d, palette=%s",
! p->depth, symbolic(v4l1_plist, p->palette));
for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].depth = p->depth;
! ov->frame[i].format = p->palette;
}
return 0;
}
case VIDIOCGCAPTURE:
{
! int *vf = arg;
! PDEBUG(4, "VIDIOCGCAPTURE");
! ov->sub_flag = *vf;
return 0;
}
case VIDIOCSCAPTURE:
{
! struct video_capture *vc = arg;
! PDEBUG(4, "VIDIOCSCAPTURE");
!
! if (vc->flags)
return -EINVAL;
! if (vc->decimation)
return -EINVAL;
! vc->x &= ~3L;
! vc->y &= ~1L;
! vc->y &= ~31L;
!
! if (vc->width == 0)
! vc->width = 32;
!
! vc->height /= 16;
! vc->height *= 16;
! if (vc->height == 0)
! vc->height = 16;
!
! ov->subx = vc->x;
! ov->suby = vc->y;
! ov->subw = vc->width;
! ov->subh = vc->height;
return 0;
}
case VIDIOCSWIN:
{
! struct video_window *vw = arg;
int i, result;
! PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height);
#if 0
! if (vw->flags)
return -EINVAL;
! if (vw->clipcount)
return -EINVAL;
! if (vw->height != ov->maxheight)
return -EINVAL;
! if (vw->width != ov->maxwidth)
return -EINVAL;
#endif
/* If we're collecting previous frame wait
before changing modes */
! interruptible_sleep_on(&ov->wq);
if (signal_pending(current)) return -EINTR;
! result = mode_init_regs(ov, vw->width, vw->height,
! ov->frame[0].format, ov->sub_flag);
if (result < 0)
return result;
for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].width = vw->width;
! ov->frame[i].height = vw->height;
}
return 0;
}
case VIDIOCGWIN:
{
! struct video_window *vw = arg;
! memset(vw, 0, sizeof(struct video_window));
! vw->x = 0; /* FIXME */
! vw->y = 0;
! vw->width = ov->frame[0].width;
! vw->height = ov->frame[0].height;
! vw->flags = 30;
! PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height);
return 0;
}
case VIDIOCGMBUF:
{
! struct video_mbuf *vm = arg;
int i;
!
! PDEBUG(4, "VIDIOCGMBUF");
!
! memset(vm, 0, sizeof(struct video_mbuf));
! vm->size = OV511_NUMFRAMES
! * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
! vm->frames = OV511_NUMFRAMES;
!
! vm->offsets[0] = 0;
for (i = 1; i < OV511_NUMFRAMES; i++) {
! vm->offsets[i] = vm->offsets[i-1]
! + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
}
return 0;
}
case VIDIOCMCAPTURE:
{
! struct video_mmap *vm = arg;
int ret, depth;
- unsigned int f = vm->frame;
! PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width,
! vm->height, symbolic(v4l1_plist, vm->format));
! depth = get_depth(vm->format);
if (!depth) {
! err("VIDIOCMCAPTURE: invalid format (%s)",
! symbolic(v4l1_plist, vm->format));
return -EINVAL;
}
! if (f >= OV511_NUMFRAMES) {
! err("VIDIOCMCAPTURE: invalid frame (%d)", f);
return -EINVAL;
}
! if (vm->width > ov->maxwidth
! || vm->height > ov->maxheight) {
err("VIDIOCMCAPTURE: requested dimensions too big");
return -EINVAL;
}
! if (ov->frame[f].grabstate == FRAME_GRABBING) {
! PDEBUG(4, "VIDIOCMCAPTURE: already grabbing");
! return -EBUSY;
! }
!
! if (force_palette && (vm->format != force_palette)) {
! info("palette rejected (%s)",
! symbolic(v4l1_plist, vm->format));
! return -EINVAL;
! }
!
! if ((ov->frame[f].width != vm->width) ||
! (ov->frame[f].height != vm->height) ||
! (ov->frame[f].format != vm->format) ||
! (ov->frame[f].sub_flag != ov->sub_flag) ||
! (ov->frame[f].depth != depth)) {
! PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters");
/* If we're collecting previous frame wait
before changing modes */
! interruptible_sleep_on(&ov->wq);
if (signal_pending(current)) return -EINTR;
! ret = mode_init_regs(ov, vm->width, vm->height,
! vm->format, ov->sub_flag);
#if 0
! if (ret < 0) {
! PDEBUG(1, "Got error while initializing regs ");
return ret;
- }
#endif
- ov->frame[f].width = vm->width;
- ov->frame[f].height = vm->height;
- ov->frame[f].format = vm->format;
- ov->frame[f].sub_flag = ov->sub_flag;
- ov->frame[f].depth = depth;
}
! /* Mark it as ready */
! ov->frame[f].grabstate = FRAME_READY;
! PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f);
! return ov51x_new_frame(ov, f);
}
case VIDIOCSYNC:
{
! unsigned int fnum = *((unsigned int *) arg);
! struct ov511_frame *frame;
! int rc;
! if (fnum >= OV511_NUMFRAMES) {
! err("VIDIOCSYNC: invalid frame (%d)", fnum);
return -EINVAL;
}
! frame = &ov->frame[fnum];
!
! PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum,
! frame->grabstate);
! switch (frame->grabstate) {
case FRAME_UNUSED:
return -EINVAL;
case FRAME_READY:
case FRAME_GRABBING:
case FRAME_ERROR:
redo:
! if (!ov->dev)
return -EIO;
! rc = wait_event_interruptible(frame->wq,
! (frame->grabstate == FRAME_DONE)
! || (frame->grabstate == FRAME_ERROR));
!
! if (rc)
! return rc;
! if (frame->grabstate == FRAME_ERROR) {
int ret;
! if ((ret = ov51x_new_frame(ov, fnum)) < 0)
return ret;
goto redo;
! }
! /* Fall through */
case FRAME_DONE:
! if (ov->snap_enabled && !frame->snapshot) {
int ret;
! if ((ret = ov51x_new_frame(ov, fnum)) < 0)
return ret;
goto redo;
}
! frame->grabstate = FRAME_UNUSED;
/* Reset the hardware snapshot button */
/* FIXME - Is this the best place for this? */
! if ((ov->snap_enabled) && (frame->snapshot)) {
! frame->snapshot = 0;
! ov51x_clear_snapshot(ov);
}
-
- /* Decompression, format conversion, etc... */
- ov51x_postprocess(ov, frame);
-
break;
} /* end switch */
--- 2041,2603 ----
* Buffer management
*
***************************************************************************/
! static int ov511_alloc(struct usb_ov511 *ov511)
{
int i;
! PDEBUG(4, "entered");
! down(&ov511->buf_lock);
! if (ov511->buf_state == BUF_PEND_DEALLOC) {
! ov511->buf_state = BUF_ALLOCATED;
! del_timer(&ov511->buf_timer);
}
! if (ov511->buf_state == BUF_ALLOCATED)
! goto out;
! ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE);
! if (!ov511->fbuf)
! goto error;
for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov511->frame[i].grabstate = FRAME_UNUSED;
! ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE;
! PDEBUG(4, "frame[%d] @ %p", i, ov511->frame[i].data);
!
! ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
! MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
! if (!ov511->sbuf[i].data) {
! while (--i) {
! kfree(ov511->sbuf[i].data);
! ov511->sbuf[i].data = NULL;
! }
! rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
! ov511->fbuf = NULL;
! goto error;
}
+ PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data);
}
! ov511->buf_state = BUF_ALLOCATED;
! out:
! up(&ov511->buf_lock);
PDEBUG(4, "leaving");
+ return 0;
+ error:
+ ov511->buf_state = BUF_NOT_ALLOCATED;
+ up(&ov511->buf_lock);
+ PDEBUG(4, "errored");
+ return -ENOMEM;
}
! /*
! * - You must acquire buf_lock before entering this function.
! * - Because this code will free any non-null pointer, you must be sure to null
! * them if you explicitly free them somewhere else!
! */
! static void ov511_do_dealloc(struct usb_ov511 *ov511)
{
int i;
PDEBUG(4, "entered");
! if (ov511->fbuf) {
! rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
! ov511->fbuf = NULL;
}
! for (i = 0; i < OV511_NUMFRAMES; i++) {
! if (ov511->sbuf[i].data) {
! kfree(ov511->sbuf[i].data);
! ov511->sbuf[i].data = NULL;
! }
! }
! PDEBUG(4, "buffer memory deallocated");
! ov511->buf_state = BUF_NOT_ALLOCATED;
! PDEBUG(4, "leaving");
! }
! static void ov511_buf_callback(unsigned long data)
! {
! struct usb_ov511 *ov511 = (struct usb_ov511 *)data;
! PDEBUG(4, "entered");
! down(&ov511->buf_lock);
! if (ov511->buf_state == BUF_PEND_DEALLOC)
! ov511_do_dealloc(ov511);
! up(&ov511->buf_lock);
! PDEBUG(4, "leaving");
! }
! static void ov511_dealloc(struct usb_ov511 *ov511, int now)
! {
! struct timer_list *bt = &(ov511->buf_timer);
! PDEBUG(4, "entered");
! down(&ov511->buf_lock);
! PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later");
! if (ov511->buf_state == BUF_PEND_DEALLOC) {
! ov511->buf_state = BUF_ALLOCATED;
! del_timer(bt);
}
! if (now)
! ov511_do_dealloc(ov511);
! else {
! ov511->buf_state = BUF_PEND_DEALLOC;
! init_timer(bt);
! bt->function = ov511_buf_callback;
! bt->data = (unsigned long)ov511;
! bt->expires = jiffies + buf_timeout * HZ;
! add_timer(bt);
}
! up(&ov511->buf_lock);
PDEBUG(4, "leaving");
}
/****************************************************************************
*
! * V4L API
*
***************************************************************************/
! static int ov511_open(struct video_device *dev, int flags)
{
! struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
! int err;
+ MOD_INC_USE_COUNT;
PDEBUG(4, "opening");
! down(&ov511->lock);
err = -EBUSY;
! if (ov511->user)
goto out;
! err = -ENOMEM;
! if (ov511_alloc(ov511))
goto out;
! ov511->sub_flag = 0;
! err = ov511_init_isoc(ov511);
if (err) {
! ov511_dealloc(ov511, 0);
goto out;
}
! ov511->user++;
out:
! up(&ov511->lock);
!
! if (err)
! MOD_DEC_USE_COUNT;
!
return err;
}
! static void ov511_close(struct video_device *dev)
{
! struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
PDEBUG(4, "ov511_close");
+
+ down(&ov511->lock);
! ov511->user--;
! ov511_stop_isoc(ov511);
! if (ov511->dev)
! ov511_dealloc(ov511, 0);
! up(&ov511->lock);
!
! if (!ov511->dev) {
! ov511_dealloc(ov511, 1);
! video_unregister_device(&ov511->vdev);
! kfree(ov511);
! ov511 = NULL;
! }
! MOD_DEC_USE_COUNT;
! }
! static int ov511_init_done(struct video_device *dev)
! {
! #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
! create_proc_ov511_cam((struct usb_ov511 *)dev);
! #endif
! return 0;
! }
! static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
! {
! return -EINVAL;
}
! static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
! struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
! PDEBUG(4, "IOCtl: 0x%X", cmd);
!
! if (!ov511->dev)
! return -EIO;
switch (cmd) {
case VIDIOCGCAP:
{
! struct video_capability b;
! PDEBUG (4, "VIDIOCGCAP");
! memset(&b, 0, sizeof(b));
! strcpy(b.name, "OV511 USB Camera");
! b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
! b.channels = 1;
! b.audios = 0;
! b.maxwidth = ov511->maxwidth;
! b.maxheight = ov511->maxheight;
! b.minwidth = 160;
! b.minheight = 120;
+ if (copy_to_user(arg, &b, sizeof(b)))
+ return -EFAULT;
+
return 0;
}
case VIDIOCGCHAN:
{
! struct video_channel v;
! if (copy_from_user(&v, arg, sizeof(v)))
! return -EFAULT;
! if (v.channel != 0)
return -EINVAL;
! v.flags = 0;
! v.tuners = 0;
! v.type = VIDEO_TYPE_CAMERA;
! strcpy(v.name, "Camera");
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+
return 0;
}
case VIDIOCSCHAN:
{
! int v;
! if (copy_from_user(&v, arg, sizeof(v)))
! return -EFAULT;
! if (v != 0)
return -EINVAL;
return 0;
}
case VIDIOCGPICT:
{
! struct video_picture p;
! PDEBUG (4, "VIDIOCGPICT");
! memset(&p, 0, sizeof(p));
!
! if (ov7610_get_picture(ov511, &p))
return -EIO;
+ if (copy_to_user(arg, &p, sizeof(p)))
+ return -EFAULT;
+
return 0;
}
case VIDIOCSPICT:
{
! struct video_picture p;
int i;
! PDEBUG (4, "VIDIOCSPICT");
! if (copy_from_user(&p, arg, sizeof(p)))
! return -EFAULT;
! if (!ov511_get_depth(p.palette))
return -EINVAL;
!
! if (ov7610_set_picture(ov511, &p))
! return -EIO;
+ PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov511->frame[i].depth = p.depth;
! ov511->frame[i].format = p.palette;
! ov511->frame[i].segsize = GET_SEGSIZE(p.palette);
}
return 0;
}
case VIDIOCGCAPTURE:
{
! int vf;
! PDEBUG (4, "VIDIOCGCAPTURE");
! if (copy_from_user(&vf, arg, sizeof(vf)))
! return -EFAULT;
! ov511->sub_flag = vf;
return 0;
}
case VIDIOCSCAPTURE:
{
! struct video_capture vc;
! if (copy_from_user(&vc, arg, sizeof(vc)))
! return -EFAULT;
! if (vc.flags)
return -EINVAL;
! if (vc.decimation)
return -EINVAL;
! vc.x &= ~3L;
! vc.y &= ~1L;
! vc.y &= ~31L;
!
! if (vc.width == 0)
! vc.width = 32;
!
! vc.height /= 16;
! vc.height *= 16;
! if (vc.height == 0)
! vc.height = 16;
!
! ov511->subx = vc.x;
! ov511->suby = vc.y;
! ov511->subw = vc.width;
! ov511->subh = vc.height;
return 0;
}
case VIDIOCSWIN:
{
! struct video_window vw;
int i, result;
! if (copy_from_user(&vw, arg, sizeof(vw)))
! return -EFAULT;
!
! PDEBUG (4, "VIDIOCSWIN: width=%d, height=%d",
! vw.width, vw.height);
#if 0
! if (vw.flags)
return -EINVAL;
! if (vw.clipcount)
return -EINVAL;
! if (vw.height != ov511->maxheight)
return -EINVAL;
! if (vw.width != ov511->maxwidth)
return -EINVAL;
#endif
/* If we're collecting previous frame wait
before changing modes */
! interruptible_sleep_on(&ov511->wq);
if (signal_pending(current)) return -EINTR;
! result = ov511_mode_init_regs(ov511, vw.width, vw.height,
! ov511->frame[0].format, ov511->sub_flag);
if (result < 0)
return result;
for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov511->frame[i].width = vw.width;
! ov511->frame[i].height = vw.height;
}
return 0;
}
case VIDIOCGWIN:
{
! struct video_window vw;
!
! memset(&vw, 0, sizeof(vw));
! vw.x = 0; /* FIXME */
! vw.y = 0;
! vw.width = ov511->frame[0].width;
! vw.height = ov511->frame[0].height;
! vw.flags = 30;
! PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
! if (copy_to_user(arg, &vw, sizeof(vw)))
! return -EFAULT;
return 0;
}
case VIDIOCGMBUF:
{
! struct video_mbuf vm;
int i;
!
! memset(&vm, 0, sizeof(vm));
! vm.size = OV511_NUMFRAMES * MAX_DATA_SIZE;
! vm.frames = OV511_NUMFRAMES;
! vm.offsets[0] = 0;
for (i = 1; i < OV511_NUMFRAMES; i++) {
! vm.offsets[i] = vm.offsets[i-1] + MAX_FRAME_SIZE
! + sizeof (struct timeval);
}
+ if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+ return -EFAULT;
+
return 0;
}
case VIDIOCMCAPTURE:
{
! struct video_mmap vm;
int ret, depth;
! if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
! return -EFAULT;
!
! PDEBUG(4, "CMCAPTURE");
! PDEBUG(4, "frame: %d, size: %dx%d, format: %d",
! vm.frame, vm.width, vm.height, vm.format);
! depth = ov511_get_depth(vm.format);
if (!depth) {
! err("VIDIOCMCAPTURE: invalid format (%d)", vm.format);
return -EINVAL;
}
! if ((unsigned)vm.frame >= OV511_NUMFRAMES) {
! err("VIDIOCMCAPTURE: invalid frame (%d)", vm.frame);
return -EINVAL;
}
! if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight) {
err("VIDIOCMCAPTURE: requested dimensions too big");
return -EINVAL;
}
! if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING)
! return -EBUSY;
+ /* Don't compress if the size changed */
+ if ((ov511->frame[vm.frame].width != vm.width) ||
+ (ov511->frame[vm.frame].height != vm.height) ||
+ (ov511->frame[vm.frame].format != vm.format) ||
+ (ov511->frame[vm.frame].sub_flag !=
+ ov511->sub_flag)) {
/* If we're collecting previous frame wait
before changing modes */
! interruptible_sleep_on(&ov511->wq);
if (signal_pending(current)) return -EINTR;
! ret = ov511_mode_init_regs(ov511, vm.width, vm.height,
! vm.format, ov511->sub_flag);
#if 0
! if (ret < 0)
return ret;
#endif
}
! ov511->frame[vm.frame].width = vm.width;
! ov511->frame[vm.frame].height = vm.height;
! ov511->frame[vm.frame].format = vm.format;
! ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
! ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format);
! ov511->frame[vm.frame].depth = depth;
! /* Mark it as ready */
! ov511->frame[vm.frame].grabstate = FRAME_READY;
! return ov511_new_frame(ov511, vm.frame);
}
case VIDIOCSYNC:
{
! int frame;
!
! if (copy_from_user((void *)&frame, arg, sizeof(int)))
! return -EFAULT;
! if ((unsigned)frame >= OV511_NUMFRAMES) {
! err("VIDIOCSYNC: invalid frame (%d)", frame);
return -EINVAL;
}
! PDEBUG(4, "syncing to frame %d, grabstate = %d", frame,
! ov511->frame[frame].grabstate);
! if(frame < 0 || frame >= OV511_NUMFRAMES)
! return -EINVAL;
!
! switch (ov511->frame[frame].grabstate) {
case FRAME_UNUSED:
return -EINVAL;
case FRAME_READY:
case FRAME_GRABBING:
case FRAME_ERROR:
redo:
! if (!ov511->dev)
return -EIO;
! do {
! #if 0
! init_waitqueue_head(&ov511->frame[frame].wq);
! #endif
! interruptible_sleep_on(&ov511->frame[frame].wq);
! if (signal_pending(current)) {
! if (retry_sync) {
! PDEBUG(3, "***retry sync***");
!
! /* Polling apps will destroy frames with that! */
! ov511_new_frame(ov511, frame);
! ov511->curframe = -1;
!
! /* This will request another frame. */
! if (waitqueue_active(&ov511->frame[frame].wq))
! wake_up_interruptible(&ov511->frame[frame].wq);
!
! return 0;
! } else {
! return -EINTR;
! }
! }
! } while (ov511->frame[frame].grabstate == FRAME_GRABBING);
! if (ov511->frame[frame].grabstate == FRAME_ERROR) {
int ret;
! if ((ret = ov511_new_frame(ov511, frame)) < 0)
return ret;
goto redo;
! }
case FRAME_DONE:
! if (ov511->snap_enabled && !ov511->frame[frame].snapshot) {
int ret;
! if ((ret = ov511_new_frame(ov511, frame)) < 0)
return ret;
goto redo;
}
! ov511->frame[frame].grabstate = FRAME_UNUSED;
/* Reset the hardware snapshot button */
/* FIXME - Is this the best place for this? */
! if ((ov511->snap_enabled) &&
! (ov511->frame[frame].snapshot)) {
! ov511->frame[frame].snapshot = 0;
! ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
! ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
! ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
}
break;
} /* end switch */
***************
*** 4958,5244 ****
}
case VIDIOCGFBUF:
{
! struct video_buffer *vb = arg;
! PDEBUG(4, "VIDIOCGFBUF");
! memset(vb, 0, sizeof(struct video_buffer));
return 0;
}
! case VIDIOCGUNIT:
! {
! struct video_unit *vu = arg;
!
! PDEBUG(4, "VIDIOCGUNIT");
!
! memset(vu, 0, sizeof(struct video_unit));
!
! vu->video = ov->vdev.minor;
! vu->vbi = VIDEO_NO_UNIT;
! vu->radio = VIDEO_NO_UNIT;
! vu->audio = VIDEO_NO_UNIT;
! vu->teletext = VIDEO_NO_UNIT;
!
return 0;
! }
default:
- PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd);
return -ENOIOCTLCMD;
} /* end switch */
return 0;
}
! /* This is implemented as video_generic_ioctl() in the new V4L's videodev.c */
! static int
! ov51x_v4l1_generic_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
! {
! char sbuf[128];
! void *mbuf = NULL;
! void *parg = NULL;
! int err = -EINVAL;
!
! /* Copy arguments into temp kernel buffer */
! switch (_IOC_DIR(cmd)) {
! case _IOC_NONE:
! parg = arg;
! break;
! case _IOC_READ: /* some v4l ioctls are marked wrong ... */
! case _IOC_WRITE:
! case (_IOC_WRITE | _IOC_READ):
! if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
! parg = sbuf;
! } else {
! /* too big to allocate from stack */
! mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
! if (NULL == mbuf)
! return -ENOMEM;
! parg = mbuf;
! }
!
! err = -EFAULT;
! if (copy_from_user(parg, arg, _IOC_SIZE(cmd)))
! goto out;
! break;
! }
!
! err = ov51x_v4l1_ioctl_internal(vdev->priv, cmd, parg);
! if (err == -ENOIOCTLCMD)
! err = -EINVAL;
! if (err < 0)
! goto out;
!
! /* Copy results into user buffer */
! switch (_IOC_DIR(cmd))
! {
! case _IOC_READ:
! case (_IOC_WRITE | _IOC_READ):
! if (copy_to_user(arg, parg, _IOC_SIZE(cmd)))
! err = -EFAULT;
! break;
! }
!
! out:
! if (mbuf)
! kfree(mbuf);
! return err;
! }
!
! static int
! ov51x_v4l1_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
! {
! struct usb_ov511 *ov = vdev->priv;
! int rc;
!
! if (down_interruptible(&ov->lock))
! return -EINTR;
!
! rc = ov51x_v4l1_generic_ioctl(vdev, cmd, arg);
!
! up(&ov->lock);
! return rc;
! }
!
! static inline long
! ov51x_v4l1_read(struct video_device *vdev, char *buf, unsigned long count,
! int noblock)
{
! struct usb_ov511 *ov = vdev->priv;
! int i, rc = 0, frmx = -1;
! struct ov511_frame *frame;
!
! if (down_interruptible(&ov->lock))
! return -EINTR;
PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
! if (!vdev || !buf) {
! rc = -EFAULT;
! goto error;
! }
! if (!ov->dev) {
! rc = -EIO;
! goto error;
! }
- // FIXME: Only supports two frames
/* See if a frame is completed, then use it. */
! if (ov->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */
frmx = 0;
! else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
frmx = 1;
/* If nonblocking we return immediately */
! if (noblock && (frmx == -1)) {
! rc = -EAGAIN;
! goto error;
! }
/* If no FRAME_DONE, look for a FRAME_GRABBING state. */
/* See if a frame is in process (grabbing), then use it. */
if (frmx == -1) {
! if (ov->frame[0].grabstate == FRAME_GRABBING)
frmx = 0;
! else if (ov->frame[1].grabstate == FRAME_GRABBING)
frmx = 1;
}
/* If no frame is active, start one. */
! if (frmx == -1) {
! if ((rc = ov51x_new_frame(ov, frmx = 0))) {
! err("read: ov51x_new_frame error");
! goto error;
! }
! }
! frame = &ov->frame[frmx];
restart:
! if (!ov->dev) {
! rc = -EIO;
! goto error;
! }
/* Wait while we're grabbing the image */
PDEBUG(4, "Waiting image grabbing");
! rc = wait_event_interruptible(frame->wq,
! (frame->grabstate == FRAME_DONE)
! || (frame->grabstate == FRAME_ERROR));
!
! if (rc)
! goto error;
!
PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
- PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd);
if (frame->grabstate == FRAME_ERROR) {
frame->bytes_read = 0;
! err("** ick! ** Errored frame %d", ov->curframe);
! if (ov51x_new_frame(ov, frmx)) {
! err("read: ov51x_new_frame error");
! goto error;
! }
goto restart;
}
/* Repeat until we get a snapshot frame */
! if (ov->snap_enabled)
! PDEBUG(4, "Waiting snapshot frame");
! if (ov->snap_enabled && !frame->snapshot) {
frame->bytes_read = 0;
! if ((rc = ov51x_new_frame(ov, frmx))) {
! err("read: ov51x_new_frame error");
! goto error;
! }
goto restart;
}
/* Clear the snapshot */
! if (ov->snap_enabled && frame->snapshot) {
frame->snapshot = 0;
! ov51x_clear_snapshot(ov);
}
! /* Decompression, format conversion, etc... */
! ov51x_postprocess(ov, frame);
!
! PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx,
! frame->bytes_read,
! get_frame_length(frame));
/* copy bytes to user space; we allow for partials reads */
! // if ((count + frame->bytes_read)
! // > get_frame_length((struct ov511_frame *)frame))
// count = frame->scanlength - frame->bytes_read;
/* FIXME - count hardwired to be one frame... */
! count = get_frame_length(frame);
PDEBUG(4, "Copy to user space: %ld bytes", count);
if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
PDEBUG(4, "Copy failed! %d bytes not copied", i);
! rc = -EFAULT;
! goto error;
}
frame->bytes_read += count;
PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
count, frame->bytes_read);
! /* If all data has been read... */
! if (frame->bytes_read
! >= get_frame_length(frame)) {
frame->bytes_read = 0;
- // FIXME: Only supports two frames
/* Mark it as available to be used again. */
! ov->frame[frmx].grabstate = FRAME_UNUSED;
! if ((rc = ov51x_new_frame(ov, !frmx))) {
! err("ov51x_new_frame returned error");
! goto error;
! }
}
PDEBUG(4, "read finished, returning %ld (sweet)", count);
- up(&ov->lock);
return count;
-
- error:
- up(&ov->lock);
- return rc;
}
! static int
! ov51x_v4l1_mmap(struct video_device *vdev, const char *adr, unsigned long size)
{
unsigned long start = (unsigned long)adr;
- struct usb_ov511 *ov = vdev->priv;
unsigned long page, pos;
! if (ov->dev == NULL)
return -EIO;
PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
! if (size > (((OV511_NUMFRAMES
! * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
! + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
return -EINVAL;
! if (down_interruptible(&ov->lock))
! return -EINTR;
!
! pos = (unsigned long)ov->fbuf;
while (size > 0) {
page = kvirt_to_pa(pos);
! if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
! up(&ov->lock);
return -EAGAIN;
- }
start += PAGE_SIZE;
pos += PAGE_SIZE;
if (size > PAGE_SIZE)
--- 2605,2776 ----
}
case VIDIOCGFBUF:
{
! struct video_buffer vb;
! memset(&vb, 0, sizeof(vb));
! vb.base = NULL; /* frame buffer not supported, not used */
! if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
! return -EFAULT;
return 0;
}
! case VIDIOCKEY:
return 0;
! case VIDIOCCAPTURE:
! return -EINVAL;
! case VIDIOCSFBUF:
! return -EINVAL;
! case VIDIOCGTUNER:
! case VIDIOCSTUNER:
! return -EINVAL;
! case VIDIOCGFREQ:
! case VIDIOCSFREQ:
! return -EINVAL;
! case VIDIOCGAUDIO:
! case VIDIOCSAUDIO:
! return -EINVAL;
default:
return -ENOIOCTLCMD;
} /* end switch */
return 0;
}
! static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int noblock)
{
! struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
! int i;
! int frmx = -1;
! volatile struct ov511_frame *frame;
PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
! if (!dev || !buf)
! return -EFAULT;
! if (!ov511->dev)
! return -EIO;
/* See if a frame is completed, then use it. */
! if (ov511->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */
frmx = 0;
! else if (ov511->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
frmx = 1;
/* If nonblocking we return immediately */
! if (noblock && (frmx == -1))
! return -EAGAIN;
/* If no FRAME_DONE, look for a FRAME_GRABBING state. */
/* See if a frame is in process (grabbing), then use it. */
if (frmx == -1) {
! if (ov511->frame[0].grabstate == FRAME_GRABBING)
frmx = 0;
! else if (ov511->frame[1].grabstate == FRAME_GRABBING)
frmx = 1;
}
/* If no frame is active, start one. */
! if (frmx == -1)
! ov511_new_frame(ov511, frmx = 0);
! frame = &ov511->frame[frmx];
restart:
! if (!ov511->dev)
! return -EIO;
/* Wait while we're grabbing the image */
PDEBUG(4, "Waiting image grabbing");
! while (frame->grabstate == FRAME_GRABBING) {
! interruptible_sleep_on(&ov511->frame[frmx].wq);
! if (signal_pending(current))
! return -EINTR;
! }
PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
if (frame->grabstate == FRAME_ERROR) {
frame->bytes_read = 0;
! err("** ick! ** Errored frame %d", ov511->curframe);
! if (ov511_new_frame(ov511, frmx))
! err("read: ov511_new_frame error");
goto restart;
}
/* Repeat until we get a snapshot frame */
! if (ov511->snap_enabled)
! PDEBUG (4, "Waiting snapshot frame");
! if (ov511->snap_enabled && !frame->snapshot) {
frame->bytes_read = 0;
! if (ov511_new_frame(ov511, frmx))
! err("ov511_new_frame error");
goto restart;
}
/* Clear the snapshot */
! if (ov511->snap_enabled && frame->snapshot) {
frame->snapshot = 0;
! ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
! ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
! ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
}
! PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
! frame->bytes_read, frame->scanlength);
/* copy bytes to user space; we allow for partials reads */
! // if ((count + frame->bytes_read) > frame->scanlength)
// count = frame->scanlength - frame->bytes_read;
/* FIXME - count hardwired to be one frame... */
! count = frame->width * frame->height * (frame->depth >> 3);
PDEBUG(4, "Copy to user space: %ld bytes", count);
if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
PDEBUG(4, "Copy failed! %d bytes not copied", i);
! return -EFAULT;
}
frame->bytes_read += count;
PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
count, frame->bytes_read);
! if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
frame->bytes_read = 0;
/* Mark it as available to be used again. */
! ov511->frame[frmx].grabstate = FRAME_UNUSED;
! if (ov511_new_frame(ov511, !frmx))
! err("ov511_new_frame returned error");
}
PDEBUG(4, "read finished, returning %ld (sweet)", count);
return count;
}
! static int ov511_mmap(struct video_device *dev, const char *adr,
! unsigned long size)
{
+ struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
unsigned long start = (unsigned long)adr;
unsigned long page, pos;
! if (ov511->dev == NULL)
return -EIO;
PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
! if (size > (((OV511_NUMFRAMES * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
return -EINVAL;
! pos = (unsigned long)ov511->fbuf;
while (size > 0) {
page = kvirt_to_pa(pos);
! if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
return -EAGAIN;
start += PAGE_SIZE;
pos += PAGE_SIZE;
if (size > PAGE_SIZE)
***************
*** 5247,5496 ****
size = 0;
}
- up(&ov->lock);
return 0;
}
! static struct video_device vdev_template = {
! owner: THIS_MODULE,
name: "OV511 USB Camera",
type: VID_TYPE_CAPTURE,
hardware: VID_HARDWARE_OV511,
! open: ov51x_v4l1_open,
! close: ov51x_v4l1_close,
! read: ov51x_v4l1_read,
! ioctl: ov51x_v4l1_ioctl,
! mmap: ov51x_v4l1_mmap,
};
- #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
- static int
- ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long ularg)
- {
- struct proc_dir_entry *pde = inode->u.generic_ip;
- struct usb_ov511 *ov;
- void *arg = (void *) ularg;
- int rc;
-
- if (!pde)
- return -ENOENT;
-
- ov = pde->data;
- if (!ov)
- return -ENODEV;
-
- if (!ov->dev)
- return -EIO;
-
- /* Should we pass through standard V4L IOCTLs? */
-
- switch (cmd) {
- case OV511IOC_GINTVER:
- {
- int ver = OV511_INTERFACE_VER;
-
- PDEBUG(4, "Get interface version: %d", ver);
- if (copy_to_user(arg, &ver, sizeof(ver)))
- return -EFAULT;
-
- return 0;
- }
- case OV511IOC_GUSHORT:
- {
- struct ov511_ushort_opt opt;
-
- if (copy_from_user(&opt, arg, sizeof(opt)))
- return -EFAULT;
-
- switch (opt.optnum) {
- case OV511_USOPT_BRIGHT:
- rc = sensor_get_brightness(ov, &(opt.val));
- if (rc) return rc;
- break;
- case OV511_USOPT_SAT:
- rc = sensor_get_saturation(ov, &(opt.val));
- if (rc) return rc;
- break;
- case OV511_USOPT_HUE:
- rc = sensor_get_hue(ov, &(opt.val));
- if (rc) return rc;
- break;
- case OV511_USOPT_CONTRAST:
- rc = sensor_get_contrast(ov, &(opt.val));
- if (rc) return rc;
- break;
- default:
- err("Invalid get short option number");
- return -EINVAL;
- }
-
- if (copy_to_user(arg, &opt, sizeof(opt)))
- return -EFAULT;
-
- return 0;
- }
- case OV511IOC_SUSHORT:
- {
- struct ov511_ushort_opt opt;
-
- if (copy_from_user(&opt, arg, sizeof(opt)))
- return -EFAULT;
-
- switch (opt.optnum) {
- case OV511_USOPT_BRIGHT:
- rc = sensor_set_brightness(ov, opt.val);
- if (rc) return rc;
- break;
- case OV511_USOPT_SAT:
- rc = sensor_set_saturation(ov, opt.val);
- if (rc) return rc;
- break;
- case OV511_USOPT_HUE:
- rc = sensor_set_hue(ov, opt.val);
- if (rc) return rc;
- break;
- case OV511_USOPT_CONTRAST:
- rc = sensor_set_contrast(ov, opt.val);
- if (rc) return rc;
- break;
- default:
- err("Invalid set short option number");
- return -EINVAL;
- }
-
- return 0;
- }
- case OV511IOC_GUINT:
- {
- struct ov511_uint_opt opt;
-
- if (copy_from_user(&opt, arg, sizeof(opt)))
- return -EFAULT;
-
- switch (opt.optnum) {
- case OV511_UIOPT_POWER_FREQ:
- opt.val = ov->lightfreq;
- break;
- case OV511_UIOPT_BFILTER:
- opt.val = ov->bandfilt;
- break;
- case OV511_UIOPT_LED:
- opt.val = ov->led_policy;
- break;
- case OV511_UIOPT_DEBUG:
- opt.val = debug;
- break;
- case OV511_UIOPT_COMPRESS:
- opt.val = ov->compress;
- break;
- default:
- err("Invalid get int option number");
- return -EINVAL;
- }
-
- if (copy_to_user(arg, &opt, sizeof(opt)))
- return -EFAULT;
-
- return 0;
- }
- case OV511IOC_SUINT:
- {
- struct ov511_uint_opt opt;
-
- if (copy_from_user(&opt, arg, sizeof(opt)))
- return -EFAULT;
-
- switch (opt.optnum) {
- case OV511_UIOPT_POWER_FREQ:
- rc = sensor_set_light_freq(ov, opt.val);
- if (rc) return rc;
- break;
- case OV511_UIOPT_BFILTER:
- rc = sensor_set_banding_filter(ov, opt.val);
- if (rc) return rc;
- break;
- case OV511_UIOPT_LED:
- if (opt.val <= 2) {
- ov->led_policy = opt.val;
- if (ov->led_policy == LED_OFF)
- ov51x_led_control(ov, 0);
- else if (ov->led_policy == LED_ON)
- ov51x_led_control(ov, 1);
- } else {
- return -EINVAL;
- }
- break;
- case OV511_UIOPT_DEBUG:
- if (opt.val <= 5)
- debug = opt.val;
- else
- return -EINVAL;
- break;
- case OV511_UIOPT_COMPRESS:
- ov->compress = opt.val;
- if (ov->compress) {
- if (ov->bclass == BCL_OV511)
- ov511_init_compression(ov);
- else if (ov->bclass == BCL_OV518)
- ov518_init_compression(ov);
- }
- break;
- default:
- err("Invalid get int option number");
- return -EINVAL;
- }
-
- return 0;
- }
- case OV511IOC_WI2C:
- {
- struct ov511_i2c_struct w;
-
- if (copy_from_user(&w, arg, sizeof(w)))
- return -EFAULT;
-
- return i2c_w_slave(ov, w.slave, w.reg, w.value,
- w.mask);
- }
- case OV511IOC_RI2C:
- {
- struct ov511_i2c_struct r;
-
- if (copy_from_user(&r, arg, sizeof(r)))
- return -EFAULT;
-
- rc = i2c_r_slave(ov, r.slave, r.reg);
- if (rc < 0)
- return rc;
-
- r.value = rc;
-
- if (copy_to_user(arg, &r, sizeof(r)))
- return -EFAULT;
-
- return 0;
- }
- default:
- return -EINVAL;
- } /* end switch */
-
- return 0;
- }
- #endif
-
/****************************************************************************
*
! * OV511 and sensor configuration
*
***************************************************************************/
! /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
! * the same register settings as the OV7610, since they are very similar.
! */
! static int
! ov7xx0_configure(struct usb_ov511 *ov)
{
int i, success;
int rc;
--- 2779,2809 ----
size = 0;
}
return 0;
}
! static struct video_device ov511_template = {
name: "OV511 USB Camera",
type: VID_TYPE_CAPTURE,
hardware: VID_HARDWARE_OV511,
! open: ov511_open,
! close: ov511_close,
! read: ov511_read,
! write: ov511_write,
! ioctl: ov511_ioctl,
! mmap: ov511_mmap,
! initialize: ov511_init_done,
};
/****************************************************************************
*
! * OV511/OV7610 configuration
*
***************************************************************************/
! static int ov76xx_configure(struct usb_ov511 *ov511)
{
+ struct usb_device *dev = ov511->dev;
int i, success;
int rc;
***************
*** 5519,5529 ****
{ OV511_I2C_BUS, 0x23, 0x2a },
{ OV511_I2C_BUS, 0x24, 0x10 },
{ OV511_I2C_BUS, 0x25, 0x8a },
- { OV511_I2C_BUS, 0x26, 0xa2 },
{ OV511_I2C_BUS, 0x27, 0xc2 },
{ OV511_I2C_BUS, 0x2a, 0x04 },
{ OV511_I2C_BUS, 0x2c, 0xfe },
- { OV511_I2C_BUS, 0x2d, 0x93 },
{ OV511_I2C_BUS, 0x30, 0x71 },
{ OV511_I2C_BUS, 0x31, 0x60 },
{ OV511_I2C_BUS, 0x32, 0x26 },
--- 2832,2840 ----
***************
*** 5537,5629 ****
};
static struct ov511_regvals aRegvalsNorm7620[] = {
! { OV511_I2C_BUS, 0x00, 0x00 },
! { OV511_I2C_BUS, 0x01, 0x80 },
! { OV511_I2C_BUS, 0x02, 0x80 },
! { OV511_I2C_BUS, 0x03, 0xc0 },
! { OV511_I2C_BUS, 0x06, 0x60 },
! { OV511_I2C_BUS, 0x07, 0x00 },
! { OV511_I2C_BUS, 0x0c, 0x24 },
! { OV511_I2C_BUS, 0x0c, 0x24 },
! { OV511_I2C_BUS, 0x0d, 0x24 },
! { OV511_I2C_BUS, 0x11, 0x01 },
! { OV511_I2C_BUS, 0x12, 0x24 },
! { OV511_I2C_BUS, 0x13, 0x01 },
! { OV511_I2C_BUS, 0x14, 0x84 },
{ OV511_I2C_BUS, 0x15, 0x01 },
- { OV511_I2C_BUS, 0x16, 0x03 },
- { OV511_I2C_BUS, 0x17, 0x2f },
- { OV511_I2C_BUS, 0x18, 0xcf },
- { OV511_I2C_BUS, 0x19, 0x06 },
- { OV511_I2C_BUS, 0x1a, 0xf5 },
- { OV511_I2C_BUS, 0x1b, 0x00 },
- { OV511_I2C_BUS, 0x20, 0x18 },
- { OV511_I2C_BUS, 0x21, 0x80 },
- { OV511_I2C_BUS, 0x22, 0x80 },
{ OV511_I2C_BUS, 0x23, 0x00 },
! { OV511_I2C_BUS, 0x26, 0xa2 },
! { OV511_I2C_BUS, 0x27, 0xea },
! { OV511_I2C_BUS, 0x28, 0x20 },
! { OV511_I2C_BUS, 0x29, 0x00 },
! { OV511_I2C_BUS, 0x2a, 0x10 },
! { OV511_I2C_BUS, 0x2b, 0x00 },
! { OV511_I2C_BUS, 0x2c, 0x88 },
! { OV511_I2C_BUS, 0x2d, 0x91 },
! { OV511_I2C_BUS, 0x2e, 0x80 },
! { OV511_I2C_BUS, 0x2f, 0x44 },
! { OV511_I2C_BUS, 0x60, 0x27 },
! { OV511_I2C_BUS, 0x61, 0x02 },
! { OV511_I2C_BUS, 0x62, 0x5f },
! { OV511_I2C_BUS, 0x63, 0xd5 },
! { OV511_I2C_BUS, 0x64, 0x57 },
! { OV511_I2C_BUS, 0x65, 0x83 },
! { OV511_I2C_BUS, 0x66, 0x55 },
! { OV511_I2C_BUS, 0x67, 0x92 },
! { OV511_I2C_BUS, 0x68, 0xcf },
! { OV511_I2C_BUS, 0x69, 0x76 },
! { OV511_I2C_BUS, 0x6a, 0x22 },
! { OV511_I2C_BUS, 0x6b, 0x00 },
! { OV511_I2C_BUS, 0x6c, 0x02 },
! { OV511_I2C_BUS, 0x6d, 0x44 },
! { OV511_I2C_BUS, 0x6e, 0x80 },
! { OV511_I2C_BUS, 0x6f, 0x1d },
! { OV511_I2C_BUS, 0x70, 0x8b },
! { OV511_I2C_BUS, 0x71, 0x00 },
! { OV511_I2C_BUS, 0x72, 0x14 },
! { OV511_I2C_BUS, 0x73, 0x54 },
! { OV511_I2C_BUS, 0x74, 0x00 },
! { OV511_I2C_BUS, 0x75, 0x8e },
! { OV511_I2C_BUS, 0x76, 0x00 },
! { OV511_I2C_BUS, 0x77, 0xff },
! { OV511_I2C_BUS, 0x78, 0x80 },
! { OV511_I2C_BUS, 0x79, 0x80 },
! { OV511_I2C_BUS, 0x7a, 0x80 },
! { OV511_I2C_BUS, 0x7b, 0xe2 },
! { OV511_I2C_BUS, 0x7c, 0x00 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
! PDEBUG(4, "starting configuration");
/* This looks redundant, but is necessary for WebCam 3 */
! ov->primary_i2c_slave = OV7xx0_SID;
! if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
return -1;
! if (init_ov_sensor(ov) >= 0) {
! PDEBUG(1, "OV7xx0 sensor initalized (method 1)");
} else {
/* Reset the 76xx */
! if (i2c_w(ov, 0x12, 0x80) < 0) return -1;
/* Wait for it to initialize */
! schedule_timeout(1 + 150 * HZ / 1000);
i = 0;
success = 0;
while (i <= i2c_detect_tries) {
! if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
! (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
success = 1;
break;
} else {
--- 2848,2928 ----
};
static struct ov511_regvals aRegvalsNorm7620[] = {
! { OV511_I2C_BUS, 0x10, 0xff },
! { OV511_I2C_BUS, 0x16, 0x06 },
! { OV511_I2C_BUS, 0x28, 0x24 },
! { OV511_I2C_BUS, 0x2b, 0xac },
! { OV511_I2C_BUS, 0x12, 0x00 },
! { OV511_I2C_BUS, 0x28, 0x24 },
! { OV511_I2C_BUS, 0x0f, 0x85 }, /* lg's setting */
{ OV511_I2C_BUS, 0x15, 0x01 },
{ OV511_I2C_BUS, 0x23, 0x00 },
! { OV511_I2C_BUS, 0x24, 0x10 },
! { OV511_I2C_BUS, 0x25, 0x8a },
! { OV511_I2C_BUS, 0x27, 0xe2 },
! { OV511_I2C_BUS, 0x2a, 0x00 },
! { OV511_I2C_BUS, 0x2c, 0xfe },
! { OV511_I2C_BUS, 0x30, 0x71 },
! { OV511_I2C_BUS, 0x31, 0x60 },
! { OV511_I2C_BUS, 0x32, 0x26 },
! { OV511_I2C_BUS, 0x33, 0x20 },
! { OV511_I2C_BUS, 0x34, 0x48 },
! { OV511_I2C_BUS, 0x12, 0x24 },
! { OV511_I2C_BUS, 0x11, 0x01 },
! { OV511_I2C_BUS, 0x0c, 0x24 },
! { OV511_I2C_BUS, 0x0d, 0x24 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
! PDEBUG (4, "starting configuration");
/* This looks redundant, but is necessary for WebCam 3 */
! if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
! OV7610_I2C_WRITE_ID) < 0)
! return -1;
!
! if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
! OV7610_I2C_READ_ID) < 0)
return -1;
! if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
! return -1;
!
! /* Reset the 76xx */
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
!
! /* Wait for it to initialize */
! schedule_timeout (1 + 150 * HZ / 1000);
!
! for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
! if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
! (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
! success = 1;
! continue;
! }
!
! /* Reset the 76xx */
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
! /* Wait for it to initialize */
! schedule_timeout (1 + 150 * HZ / 1000);
! /* Dummy read to sync I2C */
! if (ov511_i2c_read(dev, 0x00) < 0) return -1;
! }
!
! if (success) {
! PDEBUG(1, "I2C synced in %d attempt(s) (method 1)", i);
} else {
/* Reset the 76xx */
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
/* Wait for it to initialize */
! schedule_timeout (1 + 150 * HZ / 1000);
i = 0;
success = 0;
while (i <= i2c_detect_tries) {
! if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
! (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
success = 1;
break;
} else {
***************
*** 5631,6355 ****
}
}
! // Was (i == i2c_detect_tries) previously. This obviously used to always report
! // success. Whether anyone actually depended on that bug is unknown
! if ((i >= i2c_detect_tries) && (success == 0)) {
! err("Failed to read sensor ID. You might not have an");
! err("OV7610/20, or it may be not responding. Report");
! err("this to " EMAIL);
! err("This is only a warning. You can attempt to use");
! err("your camera anyway");
! // Only issue a warning for now
! // return -1;
} else {
! PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1);
}
}
! /* Detect sensor (sub)type */
! rc = i2c_r(ov, OV7610_REG_COM_I);
! if (rc < 0) {
! err("Error detecting sensor type");
! return -1;
! } else if ((rc & 3) == 3) {
! info("Sensor is an OV7610");
! ov->sensor = SEN_OV7610;
! } else if ((rc & 3) == 1) {
! /* I don't know what's different about the 76BE yet. */
! if (i2c_r(ov, 0x15) & 1) {
info("Sensor is an OV7620AE");
! info("PLEASE REPORT THE EXISTENCE OF THIS SENSOR TO");
! info("THE DRIVER AUTHOR");
! } else {
! info("Sensor is an OV76BE");
! }
!
! /* OV511+ will return all zero isoc data unless we
! * configure the sensor as a 7620. Someone needs to
! * find the exact reg. setting that causes this. */
! if (ov->bridge == BRG_OV511PLUS) {
! info("Enabling 511+/76BE workaround");
! ov->sensor = SEN_OV7620;
} else {
! ov->sensor = SEN_OV76BE;
}
! } else if ((rc & 3) == 0) {
! info("Sensor is an OV7620");
! ov->sensor = SEN_OV7620;
! } else {
! err("Unknown image sensor version: %d", rc & 3);
! return -1;
}
! if (ov->sensor == SEN_OV7620) {
PDEBUG(4, "Writing 7620 registers");
! if (write_regvals(ov, aRegvalsNorm7620))
return -1;
} else {
PDEBUG(4, "Writing 7610 registers");
! if (write_regvals(ov, aRegvalsNorm7610))
return -1;
}
! /* Set sensor-specific vars */
! ov->maxwidth = 640;
! ov->maxheight = 480;
! ov->minwidth = 64;
! ov->minheight = 48;
!
! // FIXME: These do not match the actual settings yet
! ov->brightness = 0x80 << 8;
! ov->contrast = 0x80 << 8;
! ov->colour = 0x80 << 8;
! ov->hue = 0x80 << 8;
return 0;
}
! /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
! static int
! ov6xx0_configure(struct usb_ov511 *ov)
{
! int rc;
static struct ov511_regvals aRegvalsNorm6x20[] = {
! { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
{ OV511_I2C_BUS, 0x11, 0x01 },
! { OV511_I2C_BUS, 0x03, 0x60 },
! { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
{ OV511_I2C_BUS, 0x07, 0xa8 },
- /* The ratio of 0x0c and 0x0d controls the white point */
{ OV511_I2C_BUS, 0x0c, 0x24 },
{ OV511_I2C_BUS, 0x0d, 0x24 },
! { OV511_I2C_BUS, 0x0f, 0x15 }, /* COMS */
! { OV511_I2C_BUS, 0x10, 0x75 }, /* AEC Exposure time */
! { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
{ OV511_I2C_BUS, 0x14, 0x04 },
! /* 0x16: 0x06 helps frame stability with moving objects */
! { OV511_I2C_BUS, 0x16, 0x06 },
! // { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
! { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
! /* 0x28: 0x05 Selects RGB format if RGB on */
! { OV511_I2C_BUS, 0x28, 0x05 },
! { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
! // { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
! { OV511_I2C_BUS, 0x2d, 0x99 },
! { OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Procesing Parameter */
! { OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */
{ OV511_I2C_BUS, 0x38, 0x8b },
! { OV511_I2C_BUS, 0x39, 0x40 },
!
! { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
! { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
! { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
!
{ OV511_I2C_BUS, 0x3d, 0x80 },
! /* These next two registers (0x4a, 0x4b) are undocumented. They
! * control the color balance */
! { OV511_I2C_BUS, 0x4a, 0x80 },
! { OV511_I2C_BUS, 0x4b, 0x80 },
! { OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */
{ OV511_I2C_BUS, 0x4e, 0xc1 },
{ OV511_I2C_BUS, 0x4f, 0x04 },
- // Do 50-53 have any effect?
- // Toggle 0x12[2] off and on here?
- { OV511_DONE_BUS, 0x0, 0x00 },
- };
-
- /* This chip is undocumented so many of these are guesses. OK=verified,
- * A=Added since 6620, U=unknown function (not a 6620 reg) */
- static struct ov511_regvals aRegvalsNorm6x30[] = {
- /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
- /*00?*/ { OV511_I2C_BUS, 0x11, 0x01 },
- /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 },
- /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
- { OV511_I2C_BUS, 0x07, 0xa8 },
- /* The ratio of 0x0c and 0x0d controls the white point */
- /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 },
- /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 },
- /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 },
-
- // /*24?*/ { OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */
- // { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
-
- // /*A*/ { OV511_I2C_BUS, 0x13, 0x21 },
- // /*A*/ { OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */
-
- // /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 },
- /* 0x16: 0x06 helps frame stability with moving objects */
- /*03?*/ { OV511_I2C_BUS, 0x16, 0x06 },
- // /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
- // 21 & 22? The suggested values look wrong. Go with default
- /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 },
- /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default
- // /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
-
- /* 0x28: 0x05 Selects RGB format if RGB on */
- // /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 },
- // /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus
-
- /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
- // /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
- // /*U*/ { OV511_I2C_BUS, 0x2c, 0xa0 },
- { OV511_I2C_BUS, 0x2d, 0x99 },
- // /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620
- // /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */
- // /*U*/ { OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary
- // /*U*/ { OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary
- // /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 },
- // /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7
- // { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
- // { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
- // { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
- /*OK*/ { OV511_I2C_BUS, 0x3d, 0x80 },
- // /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e },
- // /*U*/ { OV511_I2C_BUS, 0x40, 0x00 },
- // /*U*/ { OV511_I2C_BUS, 0x41, 0x00 },
- // /*U*/ { OV511_I2C_BUS, 0x42, 0x80 },
- // /*U*/ { OV511_I2C_BUS, 0x43, 0x3f },
- // /*U*/ { OV511_I2C_BUS, 0x44, 0x80 },
- // /*U*/ { OV511_I2C_BUS, 0x45, 0x20 },
- // /*U*/ { OV511_I2C_BUS, 0x46, 0x20 },
- // /*U*/ { OV511_I2C_BUS, 0x47, 0x80 },
- // /*U*/ { OV511_I2C_BUS, 0x48, 0x7f },
- // /*U*/ { OV511_I2C_BUS, 0x49, 0x00 },
-
- /* These next two registers (0x4a, 0x4b) are undocumented. They
- * control the color balance */
- // /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these
- // /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 },
- // /*U*/ { OV511_I2C_BUS, 0x4c, 0xd0 },
- /*d2?*/ { OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */
- /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 },
- /*04?*/ { OV511_I2C_BUS, 0x4f, 0x07 },
- // /*U*/ { OV511_I2C_BUS, 0x50, 0xff },
- /*U*/ { OV511_I2C_BUS, 0x54, 0x23 },
- // /*U*/ { OV511_I2C_BUS, 0x55, 0xff },
- // /*U*/ { OV511_I2C_BUS, 0x56, 0x12 },
- /*U*/ { OV511_I2C_BUS, 0x57, 0x81 },
- // /*U*/ { OV511_I2C_BUS, 0x58, 0x75 },
- /*U*/ { OV511_I2C_BUS, 0x59, 0x01 },
- /*U*/ { OV511_I2C_BUS, 0x5a, 0x2c },
- /*U*/ { OV511_I2C_BUS, 0x5b, 0x0f },
- // /*U*/ { OV511_I2C_BUS, 0x5c, 0x10 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
! PDEBUG(4, "starting sensor configuration");
! if (init_ov_sensor(ov) < 0) {
! err("Failed to read sensor ID. You might not have an OV6xx0,");
! err("or it may be not responding. Report this to " EMAIL);
! return -1;
! } else {
! PDEBUG(1, "OV6xx0 sensor detected");
! }
! /* Detect sensor (sub)type */
! rc = i2c_r(ov, OV7610_REG_COM_I);
! if (rc < 0) {
! err("Error detecting sensor type");
! return -1;
}
! if ((rc & 3) == 0)
! ov->sensor = SEN_OV6630;
! else if ((rc & 3) == 1)
! ov->sensor = SEN_OV6620;
! else if ((rc & 3) == 2)
! ov->sensor = SEN_OV6630;
! else if ((rc & 3) == 3)
! ov->sensor = SEN_OV6630;
!
! info("Sensor is an %s", symbolic(senlist, ov->sensor));
!
! /* Set sensor-specific vars */
! ov->maxwidth = 352;
! ov->maxheight = 288;
! ov->minwidth = 64;
! ov->minheight = 48;
!
! // FIXME: These do not match the actual settings yet
! ov->brightness = 0x80 << 8;
! ov->contrast = 0x80 << 8;
! ov->colour = 0x80 << 8;
! ov->hue = 0x80 << 8;
!
! if (ov->sensor == SEN_OV6620) {
! PDEBUG(4, "Writing 6x20 registers");
! if (write_regvals(ov, aRegvalsNorm6x20))
! return -1;
} else {
! PDEBUG(4, "Writing 6x30 registers");
! if (write_regvals(ov, aRegvalsNorm6x30))
! return -1;
! }
!
! return 0;
! }
!
! /* This initializes the KS0127 and KS0127B video decoders. */
! static int
! ks0127_configure(struct usb_ov511 *ov)
! {
! int rc;
!
! // FIXME: I don't know how to sync or reset it yet
! #if 0
! if (ov51x_init_ks_sensor(ov) < 0) {
! err("Failed to initialize the KS0127");
return -1;
- } else {
- PDEBUG(1, "KS012x(B) sensor detected");
}
- #endif
! /* Detect decoder subtype */
! rc = i2c_r(ov, 0x00);
! if (rc < 0) {
! err("Error detecting sensor type");
! return -1;
! } else if (rc & 0x08) {
! rc = i2c_r(ov, 0x3d);
if (rc < 0) {
err("Error detecting sensor type");
return -1;
! } else if ((rc & 0x0f) == 0) {
! info("Sensor is a KS0127");
! ov->sensor = SEN_KS0127;
! } else if ((rc & 0x0f) == 9) {
! info("Sensor is a KS0127B Rev. A");
! ov->sensor = SEN_KS0127B;
}
! } else {
! err("Error: Sensor is an unsupported KS0122");
! return -1;
}
/* Set sensor-specific vars */
! ov->maxwidth = 640;
! ov->maxheight = 480;
! ov->minwidth = 64;
! ov->minheight = 48;
!
! // FIXME: These do not match the actual settings yet
! ov->brightness = 0x80 << 8;
! ov->contrast = 0x80 << 8;
! ov->colour = 0x80 << 8;
! ov->hue = 0x80 << 8;
!
! /* This device is not supported yet. Bail out now... */
! err("This sensor is not supported yet.");
! return -1;
! return 0;
! }
!
! /* This initializes the SAA7111A video decoder. */
! static int
! saa7111a_configure(struct usb_ov511 *ov)
! {
! int rc;
!
! /* Since there is no register reset command, all registers must be
! * written, otherwise gives erratic results */
! static struct ov511_regvals aRegvalsNormSAA7111A[] = {
! { OV511_I2C_BUS, 0x06, 0xce },
! { OV511_I2C_BUS, 0x07, 0x00 },
! { OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */
! { OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */
! { OV511_I2C_BUS, 0x00, 0x00 },
! { OV511_I2C_BUS, 0x01, 0x00 },
! { OV511_I2C_BUS, 0x03, 0x23 },
! { OV511_I2C_BUS, 0x04, 0x00 },
! { OV511_I2C_BUS, 0x05, 0x00 },
! { OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */
! { OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */
! { OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */
! { OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */
! { OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */
! { OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */
! { OV511_I2C_BUS, 0x0f, 0x00 },
! { OV511_I2C_BUS, 0x11, 0x0c },
! { OV511_I2C_BUS, 0x12, 0x00 },
! { OV511_I2C_BUS, 0x13, 0x00 },
! { OV511_I2C_BUS, 0x14, 0x00 },
! { OV511_I2C_BUS, 0x15, 0x00 },
! { OV511_I2C_BUS, 0x16, 0x00 },
! { OV511_I2C_BUS, 0x17, 0x00 },
! { OV511_I2C_BUS, 0x02, 0xc0 }, /* Composite input 0 */
! { OV511_DONE_BUS, 0x0, 0x00 },
! };
!
! // FIXME: I don't know how to sync or reset it yet
! #if 0
! if (ov51x_init_saa_sensor(ov) < 0) {
! err("Failed to initialize the SAA7111A");
return -1;
- } else {
- PDEBUG(1, "SAA7111A sensor detected");
- }
- #endif
! /* 640x480 not supported with PAL */
! if (ov->pal) {
! ov->maxwidth = 320;
! ov->maxheight = 240; /* Even field only */
} else {
! ov->maxwidth = 640;
! ov->maxheight = 480; /* Even/Odd fields */
! }
!
! ov->minwidth = 320;
! ov->minheight = 240; /* Even field only */
!
! ov->has_decoder = 1;
! ov->num_inputs = 8;
! ov->norm = VIDEO_MODE_AUTO;
! ov->stop_during_set = 0; /* Decoder guarantees stable image */
!
! /* Decoder doesn't change these values, so we use these instead of
! * acutally reading the registers (which doesn't work) */
! ov->brightness = 0x80 << 8;
! ov->contrast = 0x40 << 9;
! ov->colour = 0x40 << 9;
! ov->hue = 32768;
!
! PDEBUG(4, "Writing SAA7111A registers");
! if (write_regvals(ov, aRegvalsNormSAA7111A))
! return -1;
!
! /* Detect version of decoder. This must be done after writing the
! * initial regs or the decoder will lock up. */
! rc = i2c_r(ov, 0x00);
!
! if (rc < 0) {
! err("Error detecting sensor version");
return -1;
- } else {
- info("Sensor is an SAA7111A (version 0x%x)", rc);
- ov->sensor = SEN_SAA7111A;
- }
-
- // FIXME: Fix this for OV518(+)
- /* Latch to negative edge of clock. Otherwise, we get incorrect
- * colors and jitter in the digital signal. */
- if (ov->bclass == BCL_OV511)
- reg_w(ov, 0x11, 0x00);
- else
- warn("SAA7111A not yet supported with OV518/OV518+");
-
- return 0;
- }
-
- /* This initializes the OV511/OV511+ and the sensor */
- static int
- ov511_configure(struct usb_ov511 *ov)
- {
- static struct ov511_regvals aRegvalsInit511[] = {
- { OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
- { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
- { OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
- { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
- { OV511_REG_BUS, R51x_SYS_RESET, 0x3f },
- { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
- { OV511_REG_BUS, R51x_SYS_RESET, 0x3d },
- { OV511_DONE_BUS, 0x0, 0x00},
- };
-
- static struct ov511_regvals aRegvalsNorm511[] = {
- { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 },
- { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 },
- { OV511_REG_BUS, R51x_SYS_SNAP, 0x03 },
- { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 },
- { OV511_REG_BUS, R511_FIFO_OPTS, 0x1f },
- { OV511_REG_BUS, R511_COMP_EN, 0x00 },
- { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 },
- { OV511_DONE_BUS, 0x0, 0x00 },
- };
-
- static struct ov511_regvals aRegvalsNorm511Plus[] = {
- { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0xff },
- { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 },
- { OV511_REG_BUS, R51x_SYS_SNAP, 0x03 },
- { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 },
- { OV511_REG_BUS, R511_FIFO_OPTS, 0xff },
- { OV511_REG_BUS, R511_COMP_EN, 0x00 },
- { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 },
- { OV511_DONE_BUS, 0x0, 0x00 },
- };
-
- PDEBUG(4, "");
-
- ov->customid = reg_r(ov, R511_SYS_CUST_ID);
- if (ov->customid < 0) {
- err("Unable to read camera bridge registers");
- goto error;
- }
-
- PDEBUG (1, "CustomID = %d", ov->customid);
- ov->desc = symbolic(camlist, ov->customid);
- info("model: %s", ov->desc);
-
- if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) {
- err("Camera type (%d) not recognized", ov->customid);
- err("Please notify " EMAIL " of the name,");
- err("manufacturer, model, and this number of your camera.");
- err("Also include the output of the detection process.");
- }
-
- if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */
- ov->pal = 1;
-
- if (write_regvals(ov, aRegvalsInit511)) goto error;
-
- if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
- ov51x_led_control(ov, 0);
-
- /* The OV511+ has undocumented bits in the flow control register.
- * Setting it to 0xff fixes the corruption with moving objects. */
- if (ov->bridge == BRG_OV511) {
- if (write_regvals(ov, aRegvalsNorm511)) goto error;
- } else if (ov->bridge == BRG_OV511PLUS) {
- if (write_regvals(ov, aRegvalsNorm511Plus)) goto error;
- } else {
- err("Invalid bridge");
}
! if (ov511_init_compression(ov)) goto error;
!
! ov->packet_numbering = 1;
! ov511_set_packet_size(ov, 0);
!
! ov->snap_enabled = snapshot;
!
! /* Test for 7xx0 */
! PDEBUG(3, "Testing for 0V7xx0");
! ov->primary_i2c_slave = OV7xx0_SID;
! if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
! goto error;
!
! if (i2c_w(ov, 0x12, 0x80) < 0) {
! /* Test for 6xx0 */
! PDEBUG(3, "Testing for 0V6xx0");
! ov->primary_i2c_slave = OV6xx0_SID;
! if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
! goto error;
!
! if (i2c_w(ov, 0x12, 0x80) < 0) {
! /* Test for 8xx0 */
! PDEBUG(3, "Testing for 0V8xx0");
! ov->primary_i2c_slave = OV8xx0_SID;
! if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0)
! goto error;
!
! if (i2c_w(ov, 0x12, 0x80) < 0) {
! /* Test for SAA7111A */
! PDEBUG(3, "Testing for SAA7111A");
! ov->primary_i2c_slave = SAA7111A_SID;
! if (ov51x_set_slave_ids(ov, SAA7111A_SID) < 0)
! goto error;
!
! if (i2c_w(ov, 0x0d, 0x00) < 0) {
! /* Test for KS0127 */
! PDEBUG(3, "Testing for KS0127");
! ov->primary_i2c_slave = KS0127_SID;
! if (ov51x_set_slave_ids(ov, KS0127_SID) < 0)
! goto error;
!
! if (i2c_w(ov, 0x10, 0x00) < 0) {
! err("Can't determine sensor slave IDs");
! goto error;
! } else {
! if (ks0127_configure(ov) < 0) {
! err("Failed to configure KS0127");
! goto error;
! }
! }
! } else {
! if (saa7111a_configure(ov) < 0) {
! err("Failed to configure SAA7111A");
! goto error;
! }
! }
! } else {
! err("Detected unsupported OV8xx0 sensor");
! goto error;
! }
! } else {
! if (ov6xx0_configure(ov) < 0) {
! err("Failed to configure OV6xx0");
! goto error;
! }
! }
} else {
! if (ov7xx0_configure(ov) < 0) {
! err("Failed to configure OV7xx0");
! goto error;
! }
}
return 0;
-
- error:
- err("OV511 Config failed");
-
- return -EBUSY;
}
! /* This initializes the OV518/OV518+ and the sensor */
! static int
! ov518_configure(struct usb_ov511 *ov)
{
! /* For 518 and 518+ */
! static struct ov511_regvals aRegvalsInit518[] = {
! { OV511_REG_BUS, R51x_SYS_RESET, 0x40 },
! { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
! { OV511_REG_BUS, R51x_SYS_RESET, 0x3e },
! { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
! { OV511_REG_BUS, R51x_SYS_RESET, 0x00 },
! { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
! { OV511_REG_BUS, 0x46, 0x00 },
! { OV511_REG_BUS, 0x5d, 0x03 },
! { OV511_DONE_BUS, 0x0, 0x00},
! };
! static struct ov511_regvals aRegvalsNorm518[] = {
! { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */
! { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */
! { OV511_REG_BUS, 0x31, 0x0f },
! { OV511_REG_BUS, 0x5d, 0x03 },
! { OV511_REG_BUS, 0x24, 0x9f },
! { OV511_REG_BUS, 0x25, 0x90 },
! { OV511_REG_BUS, 0x20, 0x00 }, /* Was 0x08 */
! { OV511_REG_BUS, 0x51, 0x04 },
! { OV511_REG_BUS, 0x71, 0x19 },
! { OV511_DONE_BUS, 0x0, 0x00 },
};
! static struct ov511_regvals aRegvalsNorm518Plus[] = {
! { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */
! { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */
! { OV511_REG_BUS, 0x31, 0x0f },
! { OV511_REG_BUS, 0x5d, 0x03 },
! { OV511_REG_BUS, 0x24, 0x9f },
! { OV511_REG_BUS, 0x25, 0x90 },
! { OV511_REG_BUS, 0x20, 0x60 }, /* Was 0x08 */
! { OV511_REG_BUS, 0x51, 0x02 },
! { OV511_REG_BUS, 0x71, 0x19 },
! { OV511_REG_BUS, 0x40, 0xff },
! { OV511_REG_BUS, 0x41, 0x42 },
! { OV511_REG_BUS, 0x46, 0x00 },
! { OV511_REG_BUS, 0x33, 0x04 },
! { OV511_REG_BUS, 0x21, 0x19 },
! { OV511_REG_BUS, 0x3f, 0x10 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
! PDEBUG(4, "");
!
! /* First 5 bits of custom ID reg are a revision ID on OV518 */
! info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID));
!
! /* Give it the default description */
! ov->desc = symbolic(camlist, 0);
!
! if (write_regvals(ov, aRegvalsInit518)) goto error;
!
! /* Set LED GPIO pin to output mode */
! if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) goto error;
!
! /* LED is off by default with OV518; have to explicitly turn it on */
! if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
! ov51x_led_control(ov, 0);
! else
! ov51x_led_control(ov, 1);
!
! /* Don't require compression if dumppix is enabled; otherwise it's
! * required. OV518 has no uncompressed mode, to save RAM. */
! if (!dumppix && !ov->compress) {
! ov->compress = 1;
! warn("Compression required with OV518...enabling");
! }
!
! if (ov->bridge == BRG_OV518) {
! if (write_regvals(ov, aRegvalsNorm518)) goto error;
! } else if (ov->bridge == BRG_OV518PLUS) {
! if (write_regvals(ov, aRegvalsNorm518Plus)) goto error;
! } else {
! err("Invalid bridge");
! }
! if (reg_w(ov, 0x2f, 0x80) < 0) goto error;
! if (ov518_init_compression(ov)) goto error;
! /* OV518+ has packet numbering turned on by default */
! if (ov->bridge == BRG_OV518)
! ov->packet_numbering = 0;
! else
! ov->packet_numbering = 1;
! ov518_set_packet_size(ov, 0);
! ov->snap_enabled = snapshot;
/* Test for 76xx */
! ov->primary_i2c_slave = OV7xx0_SID;
! if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
goto error;
! /* The OV518 must be more aggressive about sensor detection since
! * I2C write will never fail if the sensor is not present. We have
! * to try to initialize the sensor to detect its presence */
! if (init_ov_sensor(ov) < 0) {
/* Test for 6xx0 */
! ov->primary_i2c_slave = OV6xx0_SID;
! if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
goto error;
! if (init_ov_sensor(ov) < 0) {
! /* Test for 8xx0 */
! ov->primary_i2c_slave = OV8xx0_SID;
! if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0)
! goto error;
! if (init_ov_sensor(ov) < 0) {
! err("Can't determine sensor slave IDs");
! goto error;
! } else {
! err("Detected unsupported OV8xx0 sensor");
! goto error;
! }
! } else {
! if (ov6xx0_configure(ov) < 0) {
! err("Failed to configure OV6xx0");
! goto error;
! }
}
} else {
! if (ov7xx0_configure(ov) < 0) {
! err("Failed to configure OV7xx0");
goto error;
}
}
! ov->maxwidth = 352;
! ov->maxheight = 288;
!
! // The OV518 cannot go as low as the sensor can
! ov->minwidth = 160;
! ov->minheight = 120;
return 0;
!
error:
! err("OV518 Config failed");
! return -EBUSY;
}
--- 2930,3240 ----
}
}
! if ((i == i2c_detect_tries) && (success == 0)) {
! err("Failed to read sensor ID. You might not have an OV7610/20,");
! err("or it may be not responding. Report this to");
! err("mwm@i.am");
! return -1;
} else {
! PDEBUG(1, "I2C synced in %d attempt(s) (method 2)", i+1);
}
}
! /* Detect sensor if user didn't use override param */
! if (sensor == 0) {
! rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
! if (rc < 0) {
! err("Error detecting sensor type");
! return -1;
! } else if((rc & 3) == 3) {
! info("Sensor is an OV7610");
! ov511->sensor = SEN_OV7610;
! } else if((rc & 3) == 1) {
info("Sensor is an OV7620AE");
! ov511->sensor = SEN_OV7620AE;
! } else if((rc & 3) == 0) {
! info("Sensor is an OV7620");
! ov511->sensor = SEN_OV7620;
} else {
! err("Unknown image sensor version: %d", rc & 3);
! return -1;
}
! } else { /* sensor != 0; user overrode detection */
! ov511->sensor = sensor;
! info("Sensor set to type %d", ov511->sensor);
}
! if (ov511->sensor == SEN_OV7620) {
PDEBUG(4, "Writing 7620 registers");
! if (ov511_write_regvals(dev, aRegvalsNorm7620))
return -1;
} else {
PDEBUG(4, "Writing 7610 registers");
! if (ov511_write_regvals(dev, aRegvalsNorm7610))
! return -1;
! }
!
! /* Set sensor-specific vars */
! ov511->maxwidth = 640;
! ov511->maxheight = 480;
!
! if (aperture < 0) { /* go with the default */
! if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
! } else if (aperture <= 0xf) { /* user overrode default */
! if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
return -1;
+ } else {
+ err("Invalid setting for aperture; legal value: 0 - 15");
+ return -1;
}
! if (autoadjust) {
! if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
! if (ov511_i2c_write(dev, 0x2d,
! ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
! } else {
! if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
! if (ov511_i2c_write(dev, 0x2d,
! ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
! ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
! }
return 0;
}
! static int ov6xx0_configure(struct usb_ov511 *ov511)
{
! struct usb_device *dev = ov511->dev;
! int i, success, rc;
static struct ov511_regvals aRegvalsNorm6x20[] = {
! { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
{ OV511_I2C_BUS, 0x11, 0x01 },
! { OV511_I2C_BUS, 0x03, 0xd0 },
! { OV511_I2C_BUS, 0x05, 0x7f },
{ OV511_I2C_BUS, 0x07, 0xa8 },
{ OV511_I2C_BUS, 0x0c, 0x24 },
{ OV511_I2C_BUS, 0x0d, 0x24 },
! { OV511_I2C_BUS, 0x10, 0xff }, /* ? */
{ OV511_I2C_BUS, 0x14, 0x04 },
! { OV511_I2C_BUS, 0x16, 0x06 }, /* ? */
! { OV511_I2C_BUS, 0x19, 0x04 },
! { OV511_I2C_BUS, 0x1a, 0x93 },
! { OV511_I2C_BUS, 0x20, 0x28 },
! { OV511_I2C_BUS, 0x27, 0xa2 },
! { OV511_I2C_BUS, 0x28, 0x24 },
! { OV511_I2C_BUS, 0x2a, 0x04 }, /* 84? */
! { OV511_I2C_BUS, 0x2b, 0xac }, /* a8? */
! { OV511_I2C_BUS, 0x2d, 0x95 },
! { OV511_I2C_BUS, 0x33, 0x28 },
! { OV511_I2C_BUS, 0x34, 0xc7 },
{ OV511_I2C_BUS, 0x38, 0x8b },
! { OV511_I2C_BUS, 0x3c, 0x5c },
{ OV511_I2C_BUS, 0x3d, 0x80 },
! { OV511_I2C_BUS, 0x3f, 0x00 },
! { OV511_I2C_BUS, 0x4a, 0x80 }, /* undocumented */
! { OV511_I2C_BUS, 0x4b, 0x80 }, /* undocumented */
! { OV511_I2C_BUS, 0x4d, 0xd2 },
{ OV511_I2C_BUS, 0x4e, 0xc1 },
{ OV511_I2C_BUS, 0x4f, 0x04 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
! PDEBUG (4, "starting sensor configuration");
!
! /* Reset the 6xx0 */
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
! /* Wait for it to initialize */
! schedule_timeout (1 + 150 * HZ / 1000);
! for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
! if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
! (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
! success = 1;
! continue;
! }
! /* Reset the 6xx0 */
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
! /* Wait for it to initialize */
! schedule_timeout (1 + 150 * HZ / 1000);
! /* Dummy read to sync I2C */
! if (ov511_i2c_read(dev, 0x00) < 0) return -1;
}
! if (success) {
! PDEBUG(1, "I2C synced in %d attempt(s)", i);
} else {
! err("Failed to read sensor ID. You might not have an OV6xx0,");
! err("or it may be not responding. Report this to");
! err("mwm@i.am");
return -1;
}
! /* Detect sensor if user didn't use override param */
! if (sensor == 0) {
! rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
!
if (rc < 0) {
err("Error detecting sensor type");
return -1;
! } else {
! info("Sensor is an OV6xx0 (version %d)", rc & 3);
! ov511->sensor = SEN_OV6620;
}
! } else { /* sensor != 0; user overrode detection */
! ov511->sensor = sensor;
! info("Sensor set to type %d", ov511->sensor);
}
/* Set sensor-specific vars */
! ov511->maxwidth = 352;
! ov511->maxheight = 288;
! PDEBUG(4, "Writing 6x20 registers");
! if (ov511_write_regvals(dev, aRegvalsNorm6x20))
return -1;
! if (aperture < 0) { /* go with the default */
! if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
! } else if (aperture <= 0xf) { /* user overrode default */
! if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
! return -1;
} else {
! err("Invalid setting for aperture; legal value: 0 - 15");
return -1;
}
! if (autoadjust) {
! if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
! if (ov511_i2c_write(dev, 0x2d,
! ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
} else {
! if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
! if (ov511_i2c_write(dev, 0x2d,
! ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
! ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
}
return 0;
}
!
! static int ov511_configure(struct usb_ov511 *ov511)
{
! struct usb_device *dev = ov511->dev;
! int i;
! static struct ov511_regvals aRegvalsInit[] = {
! { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
! { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
! { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
! { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
! { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3f },
! { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
! { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d },
! { OV511_DONE_BUS, 0x0, 0x00},
};
! static struct ov511_regvals aRegvalsNorm511[] = {
! { OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0x01 },
! { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x02 },
! { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x00 },
! { OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0x1f },
! { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_Y, 0x08 },
! { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_UV, 0x01 },
! { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_Y, 0x08 },
! { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_UV, 0x01 },
! { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_Y, 0x01 },
! { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_UV, 0x01 },
! { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_Y, 0x01 },
! { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_UV, 0x01 },
! { OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x06 },
! { OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
! memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
! for (i = 0; i < OV511_NUMFRAMES; i++)
! init_waitqueue_head(&ov511->frame[i].wq);
! init_waitqueue_head(&ov511->wq);
! if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
! if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
! ov511_set_packet_size(ov511, 0);
! ov511->snap_enabled = snapshot;
/* Test for 76xx */
! if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
! OV7610_I2C_WRITE_ID) < 0)
! goto error;
!
! if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
! OV7610_I2C_READ_ID) < 0)
goto error;
! if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
! goto error;
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) {
/* Test for 6xx0 */
! if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
! OV6xx0_I2C_WRITE_ID) < 0)
goto error;
! if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
! OV6xx0_I2C_READ_ID) < 0)
! goto error;
! if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
! goto error;
!
! if (ov511_i2c_write(dev, 0x12, 0x80) < 0) {
! err("Can't determine sensor slave IDs");
! goto error;
! }
!
! if(ov6xx0_configure(ov511) < 0) {
! err("failed to configure OV6xx0");
! goto error;
}
} else {
! if(ov76xx_configure(ov511) < 0) {
! err("failed to configure OV76xx");
goto error;
}
}
+
+ /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
+ * (using read() instead). */
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov511->frame[i].width = ov511->maxwidth;
+ ov511->frame[i].height = ov511->maxheight;
+ ov511->frame[i].depth = 24;
+ ov511->frame[i].bytes_read = 0;
+ ov511->frame[i].segment = 0;
+ ov511->frame[i].format = VIDEO_PALETTE_RGB24;
+ ov511->frame[i].segsize = GET_SEGSIZE(ov511->frame[i].format);
+ }
! /* Initialize to max width/height, RGB24 */
! if (ov511_mode_init_regs(ov511, ov511->maxwidth, ov511->maxheight,
! VIDEO_PALETTE_RGB24, 0) < 0)
! goto error;
return 0;
!
error:
! usb_driver_release_interface(&ov511_driver,
! &dev->actconfig->interface[ov511->iface]);
! return -EBUSY;
}
***************
*** 6360,6372 ****
***************************************************************************/
static void *
! ov51x_probe(struct usb_device *dev, unsigned int ifnum,
! const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
! struct usb_ov511 *ov;
int i;
- int registered = 0;
PDEBUG(1, "probing for device...");
--- 3245,3256 ----
***************************************************************************/
static void *
! ov511_probe(struct usb_device *dev, unsigned int ifnum,
! const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
! struct usb_ov511 *ov511;
int i;
PDEBUG(1, "probing for device...");
***************
*** 6385,6550 ****
/* Since code below may sleep, we use this as a lock */
MOD_INC_USE_COUNT;
! if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) {
! err("couldn't kmalloc ov struct");
! goto error_out;
! }
!
! memset(ov, 0, sizeof(*ov));
!
! ov->dev = dev;
! ov->iface = interface->bInterfaceNumber;
! ov->led_policy = led;
! ov->compress = compress;
! ov->lightfreq = lightfreq;
! ov->num_inputs = 1; /* Video decoder init functs. change this */
! ov->stop_during_set = !fastset;
! ov->backlight = backlight;
! ov->mirror = mirror;
! ov->auto_brt = autobright;
! ov->auto_gain = autogain;
! ov->auto_exp = autoexp;
switch (dev->descriptor.idProduct) {
! case PROD_OV511:
! ov->bridge = BRG_OV511;
! ov->bclass = BCL_OV511;
! break;
! case PROD_OV511PLUS:
! ov->bridge = BRG_OV511PLUS;
! ov->bclass = BCL_OV511;
break;
! case PROD_OV518:
! ov->bridge = BRG_OV518;
! ov->bclass = BCL_OV518;
! break;
! case PROD_OV518PLUS:
! ov->bridge = BRG_OV518PLUS;
! ov->bclass = BCL_OV518;
! break;
! case PROD_ME2CAM:
! if (dev->descriptor.idVendor != VEND_MATTEL)
goto error;
! ov->bridge = BRG_OV511PLUS;
! ov->bclass = BCL_OV511;
break;
default:
! err("Unknown product ID 0x%04x", dev->descriptor.idProduct);
! goto error_dealloc;
! }
!
! info("USB %s video device found", symbolic(brglist, ov->bridge));
!
! /* Workaround for some applications that want data in RGB
! * instead of BGR. */
! if (force_rgb)
! info("data format set to RGB");
!
! init_waitqueue_head(&ov->wq);
!
! init_MUTEX(&ov->lock); /* to 1 == available */
! init_MUTEX(&ov->buf_lock);
! init_MUTEX(&ov->param_lock);
! init_MUTEX(&ov->i2c_lock);
! init_MUTEX(&ov->cbuf_lock);
!
! ov->buf_state = BUF_NOT_ALLOCATED;
!
! /* Must be kmalloc()'ed, for DMA accessibility */
! ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL);
! if (!ov->cbuf)
goto error;
-
- if (ov->bclass == BCL_OV518) {
- if (ov518_configure(ov) < 0)
- goto error;
- } else {
- if (ov511_configure(ov) < 0)
- goto error;
}
! for (i = 0; i < OV511_NUMFRAMES; i++) {
! ov->frame[i].framenum = i;
! init_waitqueue_head(&ov->frame[i].wq);
}
! for (i = 0; i < OV511_NUMSBUF; i++) {
! ov->sbuf[i].ov = ov;
! spin_lock_init(&ov->sbuf[i].lock);
! ov->sbuf[i].n = i;
}
! /* Unnecessary? (This is done on open(). Need to make sure variables
! * are properly initialized without this before removing it, though). */
! if (ov51x_set_default_params(ov) < 0)
goto error;
! #ifdef OV511_DEBUG
! if (dump_bridge)
! ov511_dump_regs(ov);
! #endif
!
! memcpy(&ov->vdev, &vdev_template, sizeof(vdev_template));
! ov->vdev.priv = ov;
! for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
! /* Minor 0 cannot be specified; assume user wants autodetect */
! if (unit_video[i] == 0)
! break;
! if (video_register_device(&ov->vdev, VFL_TYPE_GRABBER,
! unit_video[i]) >= 0) {
! registered = 1;
! break;
! }
}
! /* Use the next available one */
! if (!registered &&
! video_register_device(&ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
err("video_register_device failed");
goto error;
}
- info("Device registered on minor %d", ov->vdev.minor);
-
- #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
- create_proc_ov511_cam(ov);
- #endif
-
MOD_DEC_USE_COUNT;
! return ov;
error:
! #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
! /* Safe to call even if entry doesn't exist */
! destroy_proc_ov511_cam(ov);
! #endif
!
! if (ov->cbuf) {
! down(&ov->cbuf_lock);
! kfree(ov->cbuf);
! ov->cbuf = NULL;
! up(&ov->cbuf_lock);
! }
!
! error_dealloc:
! if (ov) {
! kfree(ov);
! ov = NULL;
}
- error_out:
MOD_DEC_USE_COUNT;
- err("Camera initialization failed");
return NULL;
}
static void
! ov51x_disconnect(struct usb_device *dev, void *ptr)
{
! struct usb_ov511 *ov = (struct usb_ov511 *) ptr;
int n;
MOD_INC_USE_COUNT;
--- 3269,3370 ----
/* Since code below may sleep, we use this as a lock */
MOD_INC_USE_COUNT;
! if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
! err("couldn't kmalloc ov511 struct");
! goto error;
! }
!
! memset(ov511, 0, sizeof(*ov511));
!
! ov511->dev = dev;
! ov511->iface = interface->bInterfaceNumber;
switch (dev->descriptor.idProduct) {
! case 0x0511:
! info("USB OV511 camera found");
! ov511->bridge = BRG_OV511;
! break;
! case 0xA511:
! info("USB OV511+ camera found");
! ov511->bridge = BRG_OV511PLUS;
break;
! case 0x0002:
! if (dev->descriptor.idVendor != 0x0813)
goto error;
! info("Intel Play Me2Cam (OV511+) found");
! ov511->bridge = BRG_OV511PLUS;
break;
default:
! err("Unknown product ID");
goto error;
}
! ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
! if (ov511->customid < 0) {
! err("Unable to read camera bridge registers");
! goto error;
}
! ov511->desc = -1;
! PDEBUG (4, "CustomID = %d", ov511->customid);
! for (i = 0; clist[i].id >= 0; i++) {
! if (ov511->customid == clist[i].id) {
! info("camera: %s", clist[i].description);
! ov511->desc = i;
! break;
! }
}
! /* Lifeview USB Life TV not supported */
! if (clist[i].id == 38) {
! err("This device is not supported yet.");
goto error;
+ }
! if (clist[i].id == -1) {
! err("Camera type (%d) not recognized", ov511->customid);
! err("Please contact mwm@i.am to request");
! err("support for your camera.");
! }
! /* Workaround for some applications that want data in RGB
! * instead of BGR */
! if (force_rgb)
! info("data format set to RGB");
! if (!ov511_configure(ov511)) {
! ov511->user = 0;
! init_MUTEX(&ov511->lock); /* to 1 == available */
! init_MUTEX(&ov511->buf_lock);
! ov511->buf_state = BUF_NOT_ALLOCATED;
! } else {
! err("Failed to configure camera");
! goto error;
}
! if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
err("video_register_device failed");
goto error;
}
MOD_DEC_USE_COUNT;
! return ov511;
error:
! if (ov511) {
! kfree(ov511);
! ov511 = NULL;
}
MOD_DEC_USE_COUNT;
return NULL;
}
static void
! ov511_disconnect(struct usb_device *dev, void *ptr)
{
! struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
int n;
MOD_INC_USE_COUNT;
***************
*** 6552,6594 ****
PDEBUG(3, "");
/* We don't want people trying to open up the device */
! if (!ov->user)
! video_unregister_device(&ov->vdev);
else
PDEBUG(3, "Device open...deferring video_unregister_device");
for (n = 0; n < OV511_NUMFRAMES; n++)
! ov->frame[n].grabstate = FRAME_ERROR;
! ov->curframe = -1;
/* This will cause the process to request another frame */
for (n = 0; n < OV511_NUMFRAMES; n++)
! if (waitqueue_active(&ov->frame[n].wq))
! wake_up_interruptible(&ov->frame[n].wq);
! if (waitqueue_active(&ov->wq))
! wake_up_interruptible(&ov->wq);
! ov->streaming = 0;
! ov51x_unlink_isoc(ov);
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
! destroy_proc_ov511_cam(ov);
#endif
- ov->dev = NULL;
-
/* Free the memory */
! if (ov && !ov->user) {
! down(&ov->cbuf_lock);
! kfree(ov->cbuf);
! ov->cbuf = NULL;
! up(&ov->cbuf_lock);
!
! ov51x_dealloc(ov, 1);
! kfree(ov);
! ov = NULL;
}
MOD_DEC_USE_COUNT;
--- 3372,3419 ----
PDEBUG(3, "");
/* We don't want people trying to open up the device */
! if (!ov511->user)
! video_unregister_device(&ov511->vdev);
else
PDEBUG(3, "Device open...deferring video_unregister_device");
for (n = 0; n < OV511_NUMFRAMES; n++)
! ov511->frame[n].grabstate = FRAME_ERROR;
! ov511->curframe = -1;
/* This will cause the process to request another frame */
for (n = 0; n < OV511_NUMFRAMES; n++)
! if (waitqueue_active(&ov511->frame[n].wq))
! wake_up_interruptible(&ov511->frame[n].wq);
! if (waitqueue_active(&ov511->wq))
! wake_up_interruptible(&ov511->wq);
!
! ov511->streaming = 0;
! /* Unschedule all of the iso td's */
! for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
! if (ov511->sbuf[n].urb) {
! ov511->sbuf[n].urb->next = NULL;
! usb_unlink_urb(ov511->sbuf[n].urb);
! usb_free_urb(ov511->sbuf[n].urb);
! ov511->sbuf[n].urb = NULL;
! }
! }
! usb_driver_release_interface(&ov511_driver,
! &ov511->dev->actconfig->interface[ov511->iface]);
! ov511->dev = NULL;
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
! destroy_proc_ov511_cam(ov511);
#endif
/* Free the memory */
! if (ov511 && !ov511->user) {
! ov511_dealloc(ov511, 1);
! kfree(ov511);
! ov511 = NULL;
}
MOD_DEC_USE_COUNT;
***************
*** 6597,6604 ****
static struct usb_driver ov511_driver = {
name: "ov511",
id_table: device_table,
! probe: ov51x_probe,
! disconnect: ov51x_disconnect
};
--- 3422,3429 ----
static struct usb_driver ov511_driver = {
name: "ov511",
id_table: device_table,
! probe: ov511_probe,
! disconnect: ov511_disconnect
};
***************
*** 6608,6695 ****
*
***************************************************************************/
! /* Returns 0 for success */
! int
! ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518,
! int mmx)
! {
! if (ver != DECOMP_INTERFACE_VER) {
! err("Decompression module has incompatible");
! err("interface version %d", ver);
! err("Interface version %d is required", DECOMP_INTERFACE_VER);
! return -EINVAL;
! }
!
! if (!ops)
! return -EFAULT;
!
! if (mmx && !ov51x_mmx_available) {
! err("MMX not available on this system or kernel");
! return -EINVAL;
! }
!
! lock_kernel();
!
! if (ov518) {
! if (mmx) {
! if (ov518_mmx_decomp_ops)
! goto err_in_use;
! else
! ov518_mmx_decomp_ops = ops;
! } else {
! if (ov518_decomp_ops)
! goto err_in_use;
! else
! ov518_decomp_ops = ops;
! }
! } else {
! if (mmx) {
! if (ov511_mmx_decomp_ops)
! goto err_in_use;
! else
! ov511_mmx_decomp_ops = ops;
! } else {
! if (ov511_decomp_ops)
! goto err_in_use;
! else
! ov511_decomp_ops = ops;
! }
! }
!
! MOD_INC_USE_COUNT;
!
! unlock_kernel();
! return 0;
!
! err_in_use:
! unlock_kernel();
! return -EBUSY;
! }
!
! void
! ov511_deregister_decomp_module(int ov518, int mmx)
! {
! lock_kernel();
!
! if (ov518) {
! if (mmx)
! ov518_mmx_decomp_ops = NULL;
! else
! ov518_decomp_ops = NULL;
! } else {
! if (mmx)
! ov511_mmx_decomp_ops = NULL;
! else
! ov511_decomp_ops = NULL;
! }
!
! MOD_DEC_USE_COUNT;
!
! unlock_kernel();
! }
!
! static int __init
! usb_ov511_init(void)
{
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
proc_ov511_create();
--- 3433,3439 ----
*
***************************************************************************/
! static int __init usb_ov511_init(void)
{
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
proc_ov511_create();
***************
*** 6698,6726 ****
if (usb_register(&ov511_driver) < 0)
return -1;
! #if defined (__i386__)
! if (test_bit(X86_FEATURE_MMX, boot_cpu_data.x86_capability))
! ov51x_mmx_available = 1;
! #endif
!
! info(DRIVER_VERSION " : " DRIVER_DESC);
return 0;
}
! static void __exit
! usb_ov511_exit(void)
{
usb_deregister(&ov511_driver);
info("driver deregistered");
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
proc_ov511_destroy();
! #endif
}
module_init(usb_ov511_init);
module_exit(usb_ov511_exit);
-
- EXPORT_SYMBOL(ov511_register_decomp_module);
- EXPORT_SYMBOL(ov511_deregister_decomp_module);
--- 3442,3461 ----
if (usb_register(&ov511_driver) < 0)
return -1;
! info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
! static void __exit usb_ov511_exit(void)
{
usb_deregister(&ov511_driver);
info("driver deregistered");
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
proc_ov511_destroy();
! #endif
}
module_init(usb_ov511_init);
module_exit(usb_ov511_exit);
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/ov511.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/ov511.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/ov511.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/ov511.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,140 ****
#ifndef __LINUX_OV511_H
#define __LINUX_OV511_H
#include
#include
#include
- #include
#define OV511_DEBUG /* Turn on debug messages */
#ifdef OV511_DEBUG
! #define PDEBUG(level, fmt, args...) \
! if (debug >= (level)) info("[%s:%d] " fmt, \
! __PRETTY_FUNCTION__, __LINE__ , ## args)
#else
! #define PDEBUG(level, fmt, args...) do {} while(0)
#endif
- /* This macro restricts an int variable to an inclusive range */
- #define RESTRICT_TO_RANGE(v,mi,ma) { \
- if ((v) < (mi)) (v) = (mi); \
- else if ((v) > (ma)) (v) = (ma); \
- }
-
- /* --------------------------------- */
- /* DEFINES FOR OV511 AND OTHER CHIPS */
- /* --------------------------------- */
-
- /* USB IDs */
- #define VEND_OMNIVISION 0x05A9
- #define PROD_OV511 0x0511
- #define PROD_OV511PLUS 0xA511
- #define PROD_OV518 0x0518
- #define PROD_OV518PLUS 0xA518
-
- #define VEND_MATTEL 0x0813
- #define PROD_ME2CAM 0x0002
-
- /* --------------------------------- */
- /* OV51x REGISTER MNEMONICS */
- /* --------------------------------- */
-
/* Camera interface register numbers */
! #define R511_CAM_DELAY 0x10
! #define R511_CAM_EDGE 0x11
! #define R511_CAM_PXCNT 0x12
! #define R511_CAM_LNCNT 0x13
! #define R511_CAM_PXDIV 0x14
! #define R511_CAM_LNDIV 0x15
! #define R511_CAM_UV_EN 0x16
! #define R511_CAM_LINE_MODE 0x17
! #define R511_CAM_OPTS 0x18
/* Snapshot mode camera interface register numbers */
! #define R511_SNAP_FRAME 0x19
! #define R511_SNAP_PXCNT 0x1A
! #define R511_SNAP_LNCNT 0x1B
! #define R511_SNAP_PXDIV 0x1C
! #define R511_SNAP_LNDIV 0x1D
! #define R511_SNAP_UV_EN 0x1E
! #define R511_SNAP_OPTS 0x1F
/* DRAM register numbers */
! #define R511_DRAM_FLOW_CTL 0x20
! #define R511_DRAM_ARCP 0x21
! #define R511_DRAM_MRC 0x22
! #define R511_DRAM_RFC 0x23
/* ISO FIFO register numbers */
! #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */
! #define R511_FIFO_OPTS 0x31
! /* Parallel IO register numbers */
! #define R511_PIO_OPTS 0x38
! #define R511_PIO_DATA 0x39
! #define R511_PIO_BIST 0x3E
! #define R518_GPIO_IN 0x55 /* OV518(+) only */
! #define R518_GPIO_OUT 0x56 /* OV518(+) only */
! #define R518_GPIO_CTL 0x57 /* OV518(+) only */
! #define R518_GPIO_PULSE_IN 0x58 /* OV518(+) only */
! #define R518_GPIO_PULSE_CLEAR 0x59 /* OV518(+) only */
! #define R518_GPIO_PULSE_POL 0x5a /* OV518(+) only */
! #define R518_GPIO_PULSE_EN 0x5b /* OV518(+) only */
! #define R518_GPIO_RESET 0x5c /* OV518(+) only */
!
! /* I2C registers */
! #define R511_I2C_CTL 0x40
! #define R518_I2C_CTL 0x47 /* OV518(+) only */
! #define R51x_I2C_W_SID 0x41
! #define R51x_I2C_SADDR_3 0x42
! #define R51x_I2C_SADDR_2 0x43
! #define R51x_I2C_R_SID 0x44
! #define R51x_I2C_DATA 0x45
! #define R51x_I2C_CLOCK 0x46
! #define R51x_I2C_TIMEOUT 0x47
!
! /* I2C snapshot registers */
! #define R511_SI2C_SADDR_3 0x48
! #define R511_SI2C_DATA 0x49
!
! /* System control registers */
! #define R51x_SYS_RESET 0x50
! /* Reset type definitions */
! #define OV511_RESET_UDC 0x01
! #define OV511_RESET_I2C 0x02
! #define OV511_RESET_FIFO 0x04
! #define OV511_RESET_OMNICE 0x08
! #define OV511_RESET_DRAM 0x10
! #define OV511_RESET_CAM_INT 0x20
! #define OV511_RESET_OV511 0x40
! #define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */
! #define OV511_RESET_ALL 0x7F
!
! #define R511_SYS_CLOCK_DIV 0x51
! #define R51x_SYS_SNAP 0x52
! #define R51x_SYS_INIT 0x53
! #define R511_SYS_PWR_CLK 0x54 /* OV511+/OV518(+) only */
! #define R511_SYS_LED_CTL 0x55 /* OV511+ only */
! #define R511_SYS_USER 0x5E
! #define R511_SYS_CUST_ID 0x5F
!
! /* OmniCE (compression) registers */
! #define R511_COMP_PHY 0x70
! #define R511_COMP_PHUV 0x71
! #define R511_COMP_PVY 0x72
! #define R511_COMP_PVUV 0x73
! #define R511_COMP_QHY 0x74
! #define R511_COMP_QHUV 0x75
! #define R511_COMP_QVY 0x76
! #define R511_COMP_QVUV 0x77
! #define R511_COMP_EN 0x78
! #define R511_COMP_LUT_EN 0x79
! #define R511_COMP_LUT_BEGIN 0x80
!
! /* --------------------------------- */
! /* ALTERNATE NUMBERS */
! /* --------------------------------- */
/* Alternate numbers for various max packet sizes (OV511 only) */
#define OV511_ALT_SIZE_992 0
--- 1,103 ----
+
#ifndef __LINUX_OV511_H
#define __LINUX_OV511_H
#include
#include
#include
#define OV511_DEBUG /* Turn on debug messages */
#ifdef OV511_DEBUG
! # define PDEBUG(level, fmt, args...) \
! if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
#else
! # define PDEBUG(level, fmt, args...) do {} while(0)
#endif
/* Camera interface register numbers */
! #define OV511_REG_CAMERA_DELAY_MODE 0x10
! #define OV511_REG_CAMERA_EDGE_MODE 0x11
! #define OV511_REG_CAMERA_CLAMPED_PIXEL_NUM 0x12
! #define OV511_REG_CAMERA_CLAMPED_LINE_NUM 0x13
! #define OV511_REG_CAMERA_PIXEL_DIVISOR 0x14
! #define OV511_REG_CAMERA_LINE_DIVISOR 0x15
! #define OV511_REG_CAMERA_DATA_INPUT_SELECT 0x16
! #define OV511_REG_CAMERA_RESERVED_LINE_MODE 0x17
! #define OV511_REG_CAMERA_BITMASK 0x18
/* Snapshot mode camera interface register numbers */
! #define OV511_REG_SNAP_CAPTURED_FRAME 0x19
! #define OV511_REG_SNAP_CLAMPED_PIXEL_NUM 0x1A
! #define OV511_REG_SNAP_CLAMPED_LINE_NUM 0x1B
! #define OV511_REG_SNAP_PIXEL_DIVISOR 0x1C
! #define OV511_REG_SNAP_LINE_DIVISOR 0x1D
! #define OV511_REG_SNAP_DATA_INPUT_SELECT 0x1E
! #define OV511_REG_SNAP_BITMASK 0x1F
/* DRAM register numbers */
! #define OV511_REG_DRAM_ENABLE_FLOW_CONTROL 0x20
! #define OV511_REG_DRAM_READ_CYCLE_PREDICT 0x21
! #define OV511_REG_DRAM_MANUAL_READ_CYCLE 0x22
! #define OV511_REG_DRAM_REFRESH_COUNTER 0x23
/* ISO FIFO register numbers */
! #define OV511_REG_FIFO_PACKET_SIZE 0x30
! #define OV511_REG_FIFO_BITMASK 0x31
! /* PIO register numbers */
! #define OV511_REG_PIO_BITMASK 0x38
! #define OV511_REG_PIO_DATA_PORT 0x39
! #define OV511_REG_PIO_BIST 0x3E
!
! /* I2C register numbers */
! #define OV511_REG_I2C_CONTROL 0x40
! #define OV511_REG_I2C_SLAVE_ID_WRITE 0x41
! #define OV511_REG_I2C_SUB_ADDRESS_3_BYTE 0x42
! #define OV511_REG_I2C_SUB_ADDRESS_2_BYTE 0x43
! #define OV511_REG_I2C_SLAVE_ID_READ 0x44
! #define OV511_REG_I2C_DATA_PORT 0x45
! #define OV511_REG_I2C_CLOCK_PRESCALER 0x46
! #define OV511_REG_I2C_TIME_OUT_COUNTER 0x47
!
! /* I2C snapshot register numbers */
! #define OV511_REG_I2C_SNAP_SUB_ADDRESS 0x48
! #define OV511_REG_I2C_SNAP_DATA_PORT 0x49
!
! /* System control register numbers */
! #define OV511_REG_SYSTEM_RESET 0x50
! #define OV511_RESET_UDC 0x01
! #define OV511_RESET_I2C 0x02
! #define OV511_RESET_FIFO 0x04
! #define OV511_RESET_OMNICE 0x08
! #define OV511_RESET_DRAM_INTF 0x10
! #define OV511_RESET_CAMERA_INTF 0x20
! #define OV511_RESET_OV511 0x40
! #define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */
! #define OV511_RESET_ALL 0x7F
! #define OV511_REG_SYSTEM_CLOCK_DIVISOR 0x51
! #define OV511_REG_SYSTEM_SNAPSHOT 0x52
! #define OV511_REG_SYSTEM_INIT 0x53
! #define OV511_REG_SYSTEM_PWR_CLK 0x54 /* OV511+ only */
! #define OV511_REG_SYSTEM_LED_CTL 0x55 /* OV511+ only */
! #define OV511_REG_SYSTEM_USER_DEFINED 0x5E
! #define OV511_REG_SYSTEM_CUSTOM_ID 0x5F
!
! /* OmniCE register numbers */
! #define OV511_OMNICE_PREDICTION_HORIZ_Y 0x70
! #define OV511_OMNICE_PREDICTION_HORIZ_UV 0x71
! #define OV511_OMNICE_PREDICTION_VERT_Y 0x72
! #define OV511_OMNICE_PREDICTION_VERT_UV 0x73
! #define OV511_OMNICE_QUANTIZATION_HORIZ_Y 0x74
! #define OV511_OMNICE_QUANTIZATION_HORIZ_UV 0x75
! #define OV511_OMNICE_QUANTIZATION_VERT_Y 0x76
! #define OV511_OMNICE_QUANTIZATION_VERT_UV 0x77
! #define OV511_OMNICE_ENABLE 0x78
! #define OV511_OMNICE_LUT_ENABLE 0x79
! #define OV511_OMNICE_Y_LUT_BEGIN 0x80
! #define OV511_OMNICE_Y_LUT_END 0x9F
! #define OV511_OMNICE_UV_LUT_BEGIN 0xA0
! #define OV511_OMNICE_UV_LUT_END 0xBF
/* Alternate numbers for various max packet sizes (OV511 only) */
#define OV511_ALT_SIZE_992 0
***************
*** 156,175 ****
#define OV511PLUS_ALT_SIZE_769 6
#define OV511PLUS_ALT_SIZE_961 7
- /* Alternate numbers for various max packet sizes (OV518(+) only) */
- #define OV518_ALT_SIZE_0 0
- #define OV518_ALT_SIZE_128 1
- #define OV518_ALT_SIZE_256 2
- #define OV518_ALT_SIZE_384 3
- #define OV518_ALT_SIZE_512 4
- #define OV518_ALT_SIZE_640 5
- #define OV518_ALT_SIZE_768 6
- #define OV518_ALT_SIZE_896 7
-
- /* --------------------------------- */
- /* OV7610 REGISTER MNEMONICS */
- /* --------------------------------- */
-
/* OV7610 registers */
#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
#define OV7610_REG_BLUE 0x01 /* blue channel balance */
--- 119,124 ----
***************
*** 221,306 ****
/* 36-37 reserved */
#define OV7610_REG_COM_K 0x38 /* misc registers */
- /* --------------------------------- */
- /* I2C ADDRESSES */
- /* --------------------------------- */
-
- #define OV7xx0_SID 0x42
- #define OV6xx0_SID 0xC0
- #define OV8xx0_SID 0xA0
- #define KS0127_SID 0xD8
- #define SAA7111A_SID 0x48
-
- /* --------------------------------- */
- /* MISCELLANEOUS DEFINES */
- /* --------------------------------- */
! #define I2C_CLOCK_PRESCALER 0x03
#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */
#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */
- #define PIXELS_PER_SEG 256 /* Pixels per segment */
-
- #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
-
- #define OV511_NUMFRAMES 2
- #if OV511_NUMFRAMES > VIDEO_MAX_FRAME
- #error "OV511_NUMFRAMES is too high"
- #endif
! #define OV511_NUMSBUF 2
! /* Control transfers use up to 4 bytes */
! #define OV511_CBUF_SIZE 4
/* Bridge types */
enum {
- BRG_UNKNOWN,
BRG_OV511,
BRG_OV511PLUS,
- BRG_OV518,
- BRG_OV518PLUS,
- };
-
- /* Bridge classes */
- enum {
- BCL_UNKNOWN,
- BCL_OV511,
- BCL_OV518,
};
/* Sensor types */
enum {
SEN_UNKNOWN,
- SEN_OV76BE,
SEN_OV7610,
SEN_OV7620,
SEN_OV7620AE,
SEN_OV6620,
- SEN_OV6630,
- SEN_OV6630AE,
- SEN_OV6630AF,
- SEN_OV8600,
- SEN_KS0127,
- SEN_KS0127B,
- SEN_SAA7111A,
};
- // Not implemented yet
- #if 0
- /* Sensor classes */
- enum {
- SCL_UNKNOWN,
- SCL_OV7610, /* 7610, 76BE, 7620AE (for now) */
- SCL_OV7620,
- SCL_OV6620,
- SCL_OV6630, /* 6630, 6630AE, 6630AF */
- SCL_OV8600,
- SCL_KS0127, /* SEN_KS0127, SEN_KS0127B */
- SCL_SAA7111A,
- };
- #endif
-
enum {
STATE_SCANNING, /* Scanning for start */
STATE_HEADER, /* Parsing header */
--- 170,214 ----
/* 36-37 reserved */
#define OV7610_REG_COM_K 0x38 /* misc registers */
! #define SCRATCH_BUF_SIZE 512
#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */
+ #define FRAME_SIZE_PER_DESC 993 /* FIXME - Deprecated */
#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */
! #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
! // CAMERA SPECIFIC
! // FIXME - these can vary between specific models
! #define OV7610_I2C_WRITE_ID 0x42
! #define OV7610_I2C_READ_ID 0x43
! #define OV6xx0_I2C_WRITE_ID 0xC0
! #define OV6xx0_I2C_READ_ID 0xC1
!
! #define OV511_I2C_CLOCK_PRESCALER 0x03
!
! /* Prototypes */
! int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg);
! int usb_ov511_reg_write(struct usb_device *dev,
! unsigned char reg,
! unsigned char value);
/* Bridge types */
enum {
BRG_OV511,
BRG_OV511PLUS,
};
/* Sensor types */
enum {
SEN_UNKNOWN,
SEN_OV7610,
SEN_OV7620,
SEN_OV7620AE,
SEN_OV6620,
};
enum {
STATE_SCANNING, /* Scanning for start */
STATE_HEADER, /* Parsing header */
***************
*** 314,399 ****
BUF_PEND_DEALLOC, /* ov511->buf_timer is set */
};
! /* --------- Definition of ioctl interface --------- */
!
! #define OV511_INTERFACE_VER 101
!
! /* LED options */
! enum {
! LED_OFF,
! LED_ON,
! LED_AUTO,
! };
!
! /* Raw frame formats */
! enum {
! RAWFMT_INVALID,
! RAWFMT_YUV400,
! RAWFMT_YUV420,
! RAWFMT_YUV422,
! RAWFMT_GBR422,
! };
!
! /* Unsigned short option numbers */
! enum {
! OV511_USOPT_INVALID,
! OV511_USOPT_BRIGHT,
! OV511_USOPT_SAT,
! OV511_USOPT_HUE,
! OV511_USOPT_CONTRAST,
! };
!
! /* Unsigned int option numbers */
! enum {
! OV511_UIOPT_INVALID,
! OV511_UIOPT_POWER_FREQ,
! OV511_UIOPT_BFILTER,
! OV511_UIOPT_LED,
! OV511_UIOPT_DEBUG,
! OV511_UIOPT_COMPRESS,
! };
!
! struct ov511_ushort_opt {
! int optnum; /* Specific option number */
! unsigned short val;
! };
!
! struct ov511_uint_opt {
! int optnum; /* Specific option number */
! unsigned int val;
! };
!
! struct ov511_i2c_struct {
! unsigned char slave; /* Write slave ID (read ID - 1) */
! unsigned char reg; /* Index of register */
! unsigned char value; /* User sets this w/ write, driver does w/ read */
! unsigned char mask; /* Bits to be changed. Not used with read ops */
! };
!
! /* ioctls */
! #define OV511IOC_GINTVER _IOR('v', BASE_VIDIOCPRIVATE + 0, int)
! #define OV511IOC_GUSHORT _IOWR('v', BASE_VIDIOCPRIVATE + 1, \
! struct ov511_ushort_opt)
! #define OV511IOC_SUSHORT _IOW('v', BASE_VIDIOCPRIVATE + 2, \
! struct ov511_ushort_opt)
! #define OV511IOC_GUINT _IOWR('v', BASE_VIDIOCPRIVATE + 3, \
! struct ov511_uint_opt)
! #define OV511IOC_SUINT _IOW('v', BASE_VIDIOCPRIVATE + 4, \
! struct ov511_uint_opt)
! #define OV511IOC_WI2C _IOW('v', BASE_VIDIOCPRIVATE + 5, \
! struct ov511_i2c_struct)
! #define OV511IOC_RI2C _IOWR('v', BASE_VIDIOCPRIVATE + 6, \
! struct ov511_i2c_struct)
! /* ------------- End IOCTL interface -------------- */
!
! struct usb_ov511; /* Forward declaration */
struct ov511_sbuf {
! struct usb_ov511 *ov;
! unsigned char *data;
! struct urb *urb;
! spinlock_t lock;
! int n;
};
enum {
--- 222,232 ----
BUF_PEND_DEALLOC, /* ov511->buf_timer is set */
};
! struct usb_device;
struct ov511_sbuf {
! char *data;
! urb_t *urb;
};
enum {
***************
*** 415,461 ****
};
struct ov511_frame {
! int framenum; /* Index of this frame */
! unsigned char *data; /* Frame buffer */
! unsigned char *tempdata; /* Temp buffer for multi-stage conversions */
! unsigned char *rawdata; /* Raw camera data buffer */
! unsigned char *compbuf; /* Temp buffer for decompressor */
int depth; /* Bytes per pixel */
int width; /* Width application is expecting */
! int height; /* Height application is expecting */
! int rawwidth; /* Actual width of frame sent from camera */
! int rawheight; /* Actual height of frame sent from camera */
int sub_flag; /* Sub-capture mode for this frame? */
unsigned int format; /* Format for this frame */
! int compressed; /* Is frame compressed? */
volatile int grabstate; /* State of grabbing */
int scanstate; /* State of scanning */
! int bytes_recvd; /* Number of image bytes received from camera */
! long bytes_read; /* Amount that has been read() */
wait_queue_head_t wq; /* Processes waiting */
int snapshot; /* True if frame was a snapshot */
};
! #define DECOMP_INTERFACE_VER 4
!
! /* Compression module operations */
! struct ov51x_decomp_ops {
! int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *,
! int, int, int);
! int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *,
! int, int, int);
! int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *,
! int, int, int);
! struct module *owner;
! };
struct usb_ov511 {
struct video_device vdev;
--- 248,283 ----
};
struct ov511_frame {
! char *data; /* Frame buffer */
int depth; /* Bytes per pixel */
int width; /* Width application is expecting */
! int height; /* Height */
! int hdrwidth; /* Width the frame actually is */
! int hdrheight; /* Height */
int sub_flag; /* Sub-capture mode for this frame? */
unsigned int format; /* Format for this frame */
! int segsize; /* How big is each segment from the camera? */
volatile int grabstate; /* State of grabbing */
int scanstate; /* State of scanning */
! int curline; /* Line of frame we're working on */
! int curpix;
! int segment; /* Segment from the incoming data */
! long scanlength; /* uncompressed, raw data length of frame */
! long bytes_read; /* amount of scanlength that has been read from *data */
wait_queue_head_t wq; /* Processes waiting */
int snapshot; /* True if frame was a snapshot */
};
! #define OV511_NUMFRAMES 2
! #define OV511_NUMSBUF 2
struct usb_ov511 {
struct video_device vdev;
***************
*** 464,507 ****
struct usb_device *dev;
int customid;
! char *desc;
unsigned char iface;
/* Determined by sensor type */
int maxwidth;
int maxheight;
- int minwidth;
- int minheight;
int brightness;
int colour;
int contrast;
int hue;
int whiteness;
- int exposure;
- int auto_brt; /* Auto brightness enabled flag */
- int auto_gain; /* Auto gain control enabled flag */
- int auto_exp; /* Auto exposure enabled flag */
- int backlight; /* Backlight exposure algorithm flag */
- int mirror; /* Image is reversed horizontally */
-
- int led_policy; /* LED: off|on|auto; OV511+ only */
! struct semaphore lock; /* Serializes user-accessible operations */
int user; /* user count for exclusive use */
int streaming; /* Are we streaming Isochronous? */
int grabbing; /* Are we grabbing? */
int compress; /* Should the next frame be compressed? */
- int compress_inited; /* Are compression params uploaded? */
-
- int lightfreq; /* Power (lighting) frequency */
- int bandfilt; /* Banding filter enabled flag */
! unsigned char *fbuf; /* Videodev buffer area */
! unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */
! unsigned char *rawfbuf; /* Raw camera data buffer area */
int sub_flag; /* Pix Array subcapture on flag */
int subx; /* Pix Array subcapture x offset */
--- 286,313 ----
struct usb_device *dev;
int customid;
! int desc;
unsigned char iface;
/* Determined by sensor type */
int maxwidth;
int maxheight;
int brightness;
int colour;
int contrast;
int hue;
int whiteness;
! struct semaphore lock;
int user; /* user count for exclusive use */
int streaming; /* Are we streaming Isochronous? */
int grabbing; /* Are we grabbing? */
int compress; /* Should the next frame be compressed? */
! char *fbuf; /* Videodev buffer area */
int sub_flag; /* Pix Array subcapture on flag */
int subx; /* Pix Array subcapture x offset */
***************
*** 512,629 ****
int curframe; /* Current receiving sbuf */
struct ov511_frame frame[OV511_NUMFRAMES];
struct ov511_sbuf sbuf[OV511_NUMSBUF];
wait_queue_head_t wq; /* Processes waiting */
int snap_enabled; /* Snapshot mode enabled */
! int bridge; /* Type of bridge (BRG_*) */
! int bclass; /* Class of bridge (BCL_*) */
! int sensor; /* Type of image sensor chip (SEN_*) */
! int sclass; /* Type of image sensor chip (SCL_*) */
int packet_size; /* Frame size per isoc desc */
- int packet_numbering; /* Is ISO frame numbering enabled? */
struct semaphore param_lock; /* params lock for this camera */
!
! /* /proc entries, relative to /proc/video/ov511/ */
! struct proc_dir_entry *proc_devdir; /* Per-device proc directory */
! struct proc_dir_entry *proc_info; /* /info entry */
! struct proc_dir_entry *proc_button; /* /button entry */
! struct proc_dir_entry *proc_control; /* /control entry */
!
/* Framebuffer/sbuf management */
int buf_state;
struct semaphore buf_lock;
struct timer_list buf_timer;
! struct ov51x_decomp_ops *decomp_ops;
!
! /* Stop streaming while changing picture settings */
! int stop_during_set;
!
! int stopped; /* Streaming is temporarily paused */
!
! /* Video decoder stuff */
! int input; /* Composite, S-VIDEO, etc... */
! int num_inputs; /* Number of inputs */
! int norm; /* NTSC / PAL / SECAM */
! int has_decoder; /* Device has a video decoder */
! int pal; /* Device is designed for PAL resolution */
!
! /* I2C interface */
! struct semaphore i2c_lock; /* Protect I2C controller regs */
! unsigned char primary_i2c_slave; /* I2C write id of sensor */
!
! /* Control transaction stuff */
! unsigned char *cbuf; /* Buffer for payload */
! struct semaphore cbuf_lock;
};
! /* Used to represent a list of values and their respective symbolic names */
! struct symbolic_list {
int num;
char *name;
};
! #define NOT_DEFINED_STR "Unknown"
!
! /* Returns the name of the matching element in the symbolic_list array. The
! * end of the list must be marked with an element that has a NULL name.
! */
! static inline char *
! symbolic(struct symbolic_list list[], int num)
! {
! int i;
!
! for (i = 0; list[i].name != NULL; i++)
! if (list[i].num == num)
! return (list[i].name);
!
! return (NOT_DEFINED_STR);
! }
!
! /* Compression stuff */
!
! #define OV511_QUANTABLESIZE 64
! #define OV518_QUANTABLESIZE 32
!
! #define OV511_YQUANTABLE { \
! 0, 1, 1, 2, 2, 3, 3, 4, \
! 1, 1, 1, 2, 2, 3, 4, 4, \
! 1, 1, 2, 2, 3, 4, 4, 4, \
! 2, 2, 2, 3, 4, 4, 4, 4, \
! 2, 2, 3, 4, 4, 5, 5, 5, \
! 3, 3, 4, 4, 5, 5, 5, 5, \
! 3, 4, 4, 4, 5, 5, 5, 5, \
! 4, 4, 4, 4, 5, 5, 5, 5 \
! }
!
! #define OV511_UVQUANTABLE { \
! 0, 2, 2, 3, 4, 4, 4, 4, \
! 2, 2, 2, 4, 4, 4, 4, 4, \
! 2, 2, 3, 4, 4, 4, 4, 4, \
! 3, 4, 4, 4, 4, 4, 4, 4, \
! 4, 4, 4, 4, 4, 4, 4, 4, \
! 4, 4, 4, 4, 4, 4, 4, 4, \
! 4, 4, 4, 4, 4, 4, 4, 4, \
! 4, 4, 4, 4, 4, 4, 4, 4 \
! }
!
! #define OV518_YQUANTABLE { \
! 5, 4, 5, 6, 6, 7, 7, 7, \
! 5, 5, 5, 5, 6, 7, 7, 7, \
! 6, 6, 6, 6, 7, 7, 7, 8, \
! 7, 7, 6, 7, 7, 7, 8, 8 \
! }
!
! #define OV518_UVQUANTABLE { \
! 6, 6, 6, 7, 7, 7, 7, 7, \
! 6, 6, 6, 7, 7, 7, 7, 7, \
! 6, 6, 6, 7, 7, 7, 7, 8, \
! 7, 7, 7, 7, 7, 7, 8, 8 \
! }
#endif
--- 318,371 ----
int curframe; /* Current receiving sbuf */
struct ov511_frame frame[OV511_NUMFRAMES];
+ int cursbuf; /* Current receiving sbuf */
struct ov511_sbuf sbuf[OV511_NUMSBUF];
+ /* Scratch space from the Isochronous pipe */
+ unsigned char scratch[SCRATCH_BUF_SIZE];
+ int scratchlen;
+
wait_queue_head_t wq; /* Processes waiting */
int snap_enabled; /* Snapshot mode enabled */
! int bridge; /* Type of bridge (OV511 or OV511+) */
! int sensor; /* Type of image sensor chip */
int packet_size; /* Frame size per isoc desc */
+ /* proc interface */
struct semaphore param_lock; /* params lock for this camera */
! struct proc_dir_entry *proc_entry; /* /proc/ov511/videoX */
!
/* Framebuffer/sbuf management */
int buf_state;
struct semaphore buf_lock;
struct timer_list buf_timer;
+ };
! struct cam_list {
! int id;
! char *description;
};
! struct palette_list {
int num;
char *name;
};
! struct mode_list {
! int width;
! int height;
! int color; /* 0=grayscale, 1=color */
! u8 pxcnt; /* pixel counter */
! u8 lncnt; /* line counter */
! u8 pxdv; /* pixel divisor */
! u8 lndv; /* line divisor */
! u8 m420;
! u8 common_A;
! u8 common_L;
! };
#endif
+
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pegasus.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pegasus.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pegasus.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pegasus.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,58 ****
/*
! * Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
! *
* This program is free software; you can redistribute it and/or modify
! * it under the terms of the GNU General Public License version 2 as
! * published by the Free Software Foundation.
! *
*
! * ChangeLog:
! * .... Most of the time spend reading sources & docs.
! * v0.2.x First official release for the Linux kernel.
! * v0.3.0 Beutified and structured, some bugs fixed.
! * v0.3.x URBifying bulk requests and bugfixing. First relatively
! * stable release. Still can touch device's registers only
! * from top-halves.
! * v0.4.0 Control messages remained unurbified are now URBs.
! * Now we can touch the HW at any time.
! * v0.4.9 Control urbs again use process context to wait. Argh...
! * Some long standing bugs (enable_net_traffic) fixed.
! * Also nasty trick about resubmiting control urb from
! * interrupt context used. Please let me know how it
! * behaves. Pegasus II support added since this version.
! * TODO: suppressing HCD warnings spewage on disconnect.
! * v0.4.13 Ethernet address is now set at probe(), not at open()
! * time as this seems to break dhcpd.
! * v0.4.25 ethtool support added.
*/
#include
#include
#include
#include
#include
#include
- #include
- #include
#include
#include
- #include
#include "pegasus.h"
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.4.26 (2002/03/21)"
! #define DRIVER_AUTHOR "Petko Manolov "
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
#define PEGASUS_USE_INTR
#define PEGASUS_WRITE_EEPROM
- #define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
- BMSR_100FULL | BMSR_ANEGCAPABLE)
static int loopback = 0;
! static int mii_mode = 1;
static int multicast_filter_limit = 32;
static struct usb_eth_dev usb_dev_id[] = {
--- 1,67 ----
/*
! ** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
! **
! ** Copyright (c) 1999-2001 Petko Manolov (pmanolov@lnxw.com)
! **
! **
! ** ChangeLog:
! ** .... Most of the time spend reading sources & docs.
! ** v0.2.x First official release for the Linux kernel.
! ** v0.3.0 Beutified and structured, some bugs fixed.
! ** v0.3.x URBifying bulk requests and bugfixing. First relatively
! ** stable release. Still can touch device's registers only
! ** from top-halves.
! ** v0.4.0 Control messages remained unurbified are now URBs.
! ** Now we can touch the HW at any time.
! ** v0.4.9 Control urbs again use process context to wait. Argh...
! ** Some long standing bugs (enable_net_traffic) fixed.
! ** Also nasty trick about resubmiting control urb from
! ** interrupt context used. Please let me know how it
! ** behaves. Pegasus II support added since this version.
! ** TODO: suppressing HCD warnings spewage on disconnect.
! ** v0.4.13 Ethernet address is now set at probe(), not at open()
! ** time as this seems to break dhcpd.
! */
!
! /*
* This program is free software; you can redistribute it and/or modify
! * it under the terms of the GNU General Public License as published by
! * the Free Software Foundation; either version 2 of the License, or
! * (at your option) any later version.
*
! * This program is distributed in the hope that it will be useful,
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! * GNU General Public License for more details.
! *
! * You should have received a copy of the GNU General Public License
! * along with this program; if not, write to the Free Software
! * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include
#include
#include
#include
#include
#include
#include
#include
#include "pegasus.h"
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.4.22 (2001/12/07)"
! #define DRIVER_AUTHOR "Petko Manolov "
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
#define PEGASUS_USE_INTR
#define PEGASUS_WRITE_EEPROM
static int loopback = 0;
! static int mii_mode = 0;
static int multicast_filter_limit = 32;
static struct usb_eth_dev usb_dev_id[] = {
***************
*** 68,169 ****
{match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor:vid, idProduct:pid},
#include "pegasus.h"
#undef PEGASUS_DEV
! {}
};
! MODULE_AUTHOR(DRIVER_AUTHOR);
! MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_PARM(loopback, "i");
MODULE_PARM(mii_mode, "i");
MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
! MODULE_DEVICE_TABLE(usb, pegasus_ids);
! static int update_eth_regs_async(pegasus_t *);
/* Aargh!!! I _really_ hate such tweaks */
! static void ctrl_callback(struct urb *urb)
{
! pegasus_t *pegasus = urb->context;
! if (!pegasus)
return;
! switch (urb->status) {
! case 0:
! if (pegasus->flags & ETH_REGS_CHANGE) {
! pegasus->flags &= ~ETH_REGS_CHANGE;
! pegasus->flags |= ETH_REGS_CHANGED;
! update_eth_regs_async(pegasus);
return;
! }
! break;
! case -EINPROGRESS:
! return;
! case -ENOENT:
! break;
! default:
! warn("%s: status %d", __FUNCTION__, urb->status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
! wake_up(&pegasus->ctrl_wait);
}
! static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
! void *data)
{
! int ret;
unsigned char *buffer;
DECLARE_WAITQUEUE(wait, current);
! buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
! memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
! while (pegasus->flags & ETH_REGS_CHANGED)
schedule();
remove_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_RUNNING);
! pegasus->dr.bRequestType = PEGASUS_REQT_READ;
! pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS;
! pegasus->dr.wValue = cpu_to_le16(0);
! pegasus->dr.wIndex = cpu_to_le16p(&indx);
! pegasus->dr.wLength = cpu_to_le16p(&size);
! pegasus->ctrl_urb->transfer_buffer_length = size;
!
! FILL_CONTROL_URB(pegasus->ctrl_urb, pegasus->usb,
! usb_rcvctrlpipe(pegasus->usb, 0),
! (char *) &pegasus->dr,
! buffer, size, ctrl_callback, pegasus);
! add_wait_queue(&pegasus->ctrl_wait, &wait);
! set_current_state(TASK_UNINTERRUPTIBLE);
! if ((ret = usb_submit_urb(pegasus->ctrl_urb))) {
! err("%s: BAD CTRLs %d", __FUNCTION__, ret);
goto out;
}
schedule();
out:
! remove_wait_queue(&pegasus->ctrl_wait, &wait);
! memcpy(data, buffer, size);
kfree(buffer);
return ret;
}
! static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
! void *data)
{
! int ret;
unsigned char *buffer;
DECLARE_WAITQUEUE(wait, current);
--- 77,180 ----
{match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor:vid, idProduct:pid},
#include "pegasus.h"
#undef PEGASUS_DEV
! { }
};
!
! MODULE_AUTHOR( DRIVER_AUTHOR );
! MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
MODULE_PARM(loopback, "i");
MODULE_PARM(mii_mode, "i");
MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
! MODULE_DEVICE_TABLE (usb, pegasus_ids);
!
! static int update_eth_regs_async( pegasus_t * );
/* Aargh!!! I _really_ hate such tweaks */
! static void ctrl_callback( urb_t *urb )
{
! pegasus_t *pegasus = urb->context;
! if ( !pegasus )
return;
! switch ( urb->status ) {
! case USB_ST_NOERROR:
! if ( pegasus->flags & ETH_REGS_CHANGE ) {
! pegasus->flags &= ~ETH_REGS_CHANGE;
! pegasus->flags |= ETH_REGS_CHANGED;
! update_eth_regs_async( pegasus );
! return;
! }
! break;
! case USB_ST_URB_PENDING:
return;
! case USB_ST_URB_KILLED:
! break;
! default:
! warn( __FUNCTION__ " status %d", urb->status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
! wake_up(&pegasus->ctrl_wait );
}
!
! static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
{
! int ret;
unsigned char *buffer;
DECLARE_WAITQUEUE(wait, current);
! buffer = kmalloc(size,GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
! memcpy(buffer,data,size);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
! while ( pegasus->flags & ETH_REGS_CHANGED )
schedule();
remove_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_RUNNING);
! pegasus->dr.requesttype = PEGASUS_REQT_READ;
! pegasus->dr.request = PEGASUS_REQ_GET_REGS;
! pegasus->dr.value = cpu_to_le16 (0);
! pegasus->dr.index = cpu_to_le16p(&indx);
! pegasus->dr.length = cpu_to_le16p(&size);
! pegasus->ctrl_urb.transfer_buffer_length = size;
!
! FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
! usb_rcvctrlpipe(pegasus->usb,0),
! (char *)&pegasus->dr,
! buffer, size, ctrl_callback, pegasus );
! add_wait_queue( &pegasus->ctrl_wait, &wait );
! set_current_state( TASK_UNINTERRUPTIBLE );
! if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
! err( __FUNCTION__ " BAD CTRLs %d", ret);
goto out;
}
schedule();
out:
! remove_wait_queue( &pegasus->ctrl_wait, &wait );
! memcpy(data,buffer,size);
kfree(buffer);
return ret;
}
!
! static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
{
! int ret;
unsigned char *buffer;
DECLARE_WAITQUEUE(wait, current);
***************
*** 176,221 ****
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
! while (pegasus->flags & ETH_REGS_CHANGED)
schedule();
remove_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_RUNNING);
! pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
! pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
! pegasus->dr.wValue = cpu_to_le16(0);
! pegasus->dr.wIndex = cpu_to_le16p(&indx);
! pegasus->dr.wLength = cpu_to_le16p(&size);
! pegasus->ctrl_urb->transfer_buffer_length = size;
!
! FILL_CONTROL_URB(pegasus->ctrl_urb, pegasus->usb,
! usb_sndctrlpipe(pegasus->usb, 0),
! (char *) &pegasus->dr,
! buffer, size, ctrl_callback, pegasus);
!
! add_wait_queue(&pegasus->ctrl_wait, &wait);
! set_current_state(TASK_UNINTERRUPTIBLE);
! if ((ret = usb_submit_urb(pegasus->ctrl_urb))) {
! err("%s: BAD CTRL %d", __FUNCTION__, ret);
goto out;
}
!
schedule();
out:
! remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
!
return ret;
}
! static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
{
! int ret;
unsigned char *buffer;
__u16 dat = data;
DECLARE_WAITQUEUE(wait, current);
!
buffer = kmalloc(1, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
--- 187,233 ----
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
! while ( pegasus->flags & ETH_REGS_CHANGED )
schedule();
remove_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_RUNNING);
! pegasus->dr.requesttype = PEGASUS_REQT_WRITE;
! pegasus->dr.request = PEGASUS_REQ_SET_REGS;
! pegasus->dr.value = cpu_to_le16 (0);
! pegasus->dr.index = cpu_to_le16p( &indx );
! pegasus->dr.length = cpu_to_le16p( &size );
! pegasus->ctrl_urb.transfer_buffer_length = size;
!
! FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
! usb_sndctrlpipe(pegasus->usb,0),
! (char *)&pegasus->dr,
! buffer, size, ctrl_callback, pegasus );
!
! add_wait_queue( &pegasus->ctrl_wait, &wait );
! set_current_state( TASK_UNINTERRUPTIBLE );
! if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
! err( __FUNCTION__ " BAD CTRL %d", ret);
goto out;
}
!
schedule();
out:
! remove_wait_queue( &pegasus->ctrl_wait, &wait );
kfree(buffer);
!
return ret;
}
!
! static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data )
{
! int ret;
unsigned char *buffer;
__u16 dat = data;
DECLARE_WAITQUEUE(wait, current);
!
buffer = kmalloc(1, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
***************
*** 225,539 ****
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
! while (pegasus->flags & ETH_REGS_CHANGED)
schedule();
remove_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_RUNNING);
! pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
! pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
! pegasus->dr.wValue = cpu_to_le16p(&dat);
! pegasus->dr.wIndex = cpu_to_le16p(&indx);
! pegasus->dr.wLength = cpu_to_le16(1);
! pegasus->ctrl_urb->transfer_buffer_length = 1;
!
! FILL_CONTROL_URB(pegasus->ctrl_urb, pegasus->usb,
! usb_sndctrlpipe(pegasus->usb, 0),
! (char *) &pegasus->dr,
! buffer, 1, ctrl_callback, pegasus);
! add_wait_queue(&pegasus->ctrl_wait, &wait);
! set_current_state(TASK_UNINTERRUPTIBLE);
! if ((ret = usb_submit_urb(pegasus->ctrl_urb))) {
! err("%s: BAD CTRL %d", __FUNCTION__, ret);
goto out;
}
schedule();
out:
! remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret;
}
! static int update_eth_regs_async(pegasus_t * pegasus)
{
! int ret;
! pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
! pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
! pegasus->dr.wValue = 0;
! pegasus->dr.wIndex = cpu_to_le16(EthCtrl0);
! pegasus->dr.wLength = cpu_to_le16(3);
! pegasus->ctrl_urb->transfer_buffer_length = 3;
!
! FILL_CONTROL_URB(pegasus->ctrl_urb, pegasus->usb,
! usb_sndctrlpipe(pegasus->usb, 0),
! (char *) &pegasus->dr,
! pegasus->eth_regs, 3, ctrl_callback, pegasus);
!
! if ((ret = usb_submit_urb(pegasus->ctrl_urb)))
! err("%s: BAD CTRL %d, flgs %x", __FUNCTION__, ret,
! pegasus->flags);
! return ret;
}
! static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
{
! int i;
! __u8 data[4] = { phy, 0, 0, indx };
! __u16 regdi;
!
! set_register(pegasus, PhyCtrl, 0);
! set_registers(pegasus, PhyAddr, sizeof(data), data);
! set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, PhyCtrl, 1, data);
! if (data[0] & PHY_DONE)
break;
}
! if (i < REG_TIMEOUT) {
! get_registers(pegasus, PhyData, 2, ®di);
*regd = le16_to_cpu(regdi);
! return 0;
}
! warn("%s: failed", __FUNCTION__);
!
return 1;
}
- static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
- {
- int i;
- __u8 data[4] = { phy, 0, 0, indx };
! *(data + 1) = cpu_to_le16p(®d);
! set_register(pegasus, PhyCtrl, 0);
! set_registers(pegasus, PhyAddr, 4, data);
! set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, PhyCtrl, 1, data);
! if (data[0] & PHY_DONE)
break;
}
! if (i < REG_TIMEOUT)
! return 0;
! warn("%s: failed", __FUNCTION__);
return 1;
}
! static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
{
! int i;
__u8 tmp;
__u16 retdatai;
!
! set_register(pegasus, EpromCtrl, 0);
! set_register(pegasus, EpromOffset, index);
! set_register(pegasus, EpromCtrl, EPROM_READ);
!
! for (i = 0; i < REG_TIMEOUT; i++) {
! get_registers(pegasus, EpromCtrl, 1, &tmp);
! if (tmp & EPROM_DONE)
break;
}
! if (i < REG_TIMEOUT) {
! get_registers(pegasus, EpromData, 2, &retdatai);
! *retdata = le16_to_cpu(retdatai);
! return 0;
}
! warn("%s: failed", __FUNCTION__);
return -1;
}
#ifdef PEGASUS_WRITE_EEPROM
! static inline void enable_eprom_write(pegasus_t * pegasus)
{
! __u8 tmp;
! get_registers(pegasus, EthCtrl2, 1, &tmp);
! set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
}
! static inline void disable_eprom_write(pegasus_t * pegasus)
{
! __u8 tmp;
! get_registers(pegasus, EthCtrl2, 1, &tmp);
! set_register(pegasus, EpromCtrl, 0);
! set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
}
! static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
{
! int i, tmp;
! __u8 d[4] = { 0x3f, 0, 0, EPROM_WRITE };
! set_registers(pegasus, EpromOffset, 4, d);
! enable_eprom_write(pegasus);
! set_register(pegasus, EpromOffset, index);
! set_registers(pegasus, EpromData, 2, &data);
! set_register(pegasus, EpromCtrl, EPROM_WRITE);
! for (i = 0; i < REG_TIMEOUT; i++) {
! get_registers(pegasus, EpromCtrl, 1, &tmp);
! if (tmp & EPROM_DONE)
break;
}
! disable_eprom_write(pegasus);
! if (i < REG_TIMEOUT)
! return 0;
! warn("%s: failed", __FUNCTION__);
! return -1;
}
! #endif /* PEGASUS_WRITE_EEPROM */
! static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
{
! int i;
__u16 w16;
!
for (i = 0; i < 3; i++) {
! read_eprom_word(pegasus, i, &w16);
! ((__u16 *) id)[i] = cpu_to_le16p(&w16);
}
}
! static void set_ethernet_addr(pegasus_t * pegasus)
{
! __u8 node_id[6];
get_node_id(pegasus, node_id);
! set_registers(pegasus, EthID, sizeof(node_id), node_id);
! memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id));
}
! static inline int reset_mac(pegasus_t * pegasus)
{
! __u8 data = 0x8;
! int i;
set_register(pegasus, EthCtrl1, data);
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, EthCtrl1, 1, &data);
if (~data & 0x08) {
! if (loopback & 1)
break;
! if (mii_mode && (pegasus->features & HAS_HOME_PNA))
! set_register(pegasus, Gpio1, 0x34);
else
! set_register(pegasus, Gpio1, 0x26);
! set_register(pegasus, Gpio0, pegasus->features);
! set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
break;
}
}
! if (i == REG_TIMEOUT)
return 1;
! if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
! usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
! __u16 auxmode;
!
! read_mii_word(pegasus, 1, 0x1b, &auxmode);
! write_mii_word(pegasus, 1, 0x1b, auxmode | 4);
! }
! if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
! __u16 auxmode;
! read_mii_word(pegasus, 3, 0x1b, &auxmode);
! write_mii_word(pegasus, 3, 0x1b, auxmode | 4);
}
! return 0;
}
! static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
{
! __u16 linkpart, bmsr;
! __u8 data[4];
pegasus_t *pegasus = dev->priv;
! /* read twice 'cos this is a latch bit */
! read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr);
! read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr);
! if (read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart))
return 2;
! if (!(linkpart & 1))
! warn("link partner stat %x", linkpart);
data[0] = 0xc9;
data[1] = 0;
! if (linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL))
! data[1] |= 0x20; /* set full duplex */
! if (linkpart & (ADVERTISE_100FULL | ADVERTISE_100HALF))
! data[1] |= 0x10; /* set 100 Mbps */
! if (mii_mode)
data[1] = 0;
data[2] = (loopback & 1) ? 0x09 : 0x01;
! memcpy(pegasus->eth_regs, data, sizeof(data));
! set_registers(pegasus, EthCtrl0, 3, data);
return 0;
}
! static void read_bulk_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
int count = urb->actual_length, res;
int rx_status;
! struct sk_buff *skb;
__u16 pkt_len;
! if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
return;
net = pegasus->net;
! if (!netif_device_present(net))
return;
! if (pegasus->flags & PEGASUS_RX_BUSY) {
pegasus->stats.rx_errors++;
dbg("pegasus Rx busy");
return;
}
pegasus->flags |= PEGASUS_RX_BUSY;
! switch (urb->status) {
! case 0:
! break;
! case -ETIMEDOUT:
! dbg("reset MAC");
! pegasus->flags &= ~PEGASUS_RX_BUSY;
! break;
! default:
! dbg("%s: RX status %d", net->name, urb->status);
! goto goon;
}
! if (!count)
goto goon;
! rx_status = le32_to_cpu(*(int *) (pegasus->rx_buff + count - 4));
! if (rx_status & 0x000e0000) {
dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
pegasus->stats.rx_errors++;
! if (rx_status & 0x060000)
pegasus->stats.rx_length_errors++;
! if (rx_status & 0x080000)
pegasus->stats.rx_crc_errors++;
! if (rx_status & 0x100000)
pegasus->stats.rx_frame_errors++;
goto goon;
}
pkt_len = (rx_status & 0xfff) - 8;
! if (!(skb = dev_alloc_skb(pkt_len + 2)))
goto goon;
skb->dev = net;
--- 237,561 ----
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
! while ( pegasus->flags & ETH_REGS_CHANGED )
schedule();
remove_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_RUNNING);
! pegasus->dr.requesttype = PEGASUS_REQT_WRITE;
! pegasus->dr.request = PEGASUS_REQ_SET_REG;
! pegasus->dr.value = cpu_to_le16p( &dat);
! pegasus->dr.index = cpu_to_le16p( &indx );
! pegasus->dr.length = cpu_to_le16( 1 );
! pegasus->ctrl_urb.transfer_buffer_length = 1;
!
! FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
! usb_sndctrlpipe(pegasus->usb,0),
! (char *)&pegasus->dr,
! buffer, 1, ctrl_callback, pegasus );
! add_wait_queue( &pegasus->ctrl_wait, &wait );
! set_current_state( TASK_UNINTERRUPTIBLE );
! if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
! err( __FUNCTION__ " BAD CTRL %d", ret);
goto out;
}
schedule();
out:
! remove_wait_queue( &pegasus->ctrl_wait, &wait );
kfree(buffer);
return ret;
}
!
! static int update_eth_regs_async( pegasus_t *pegasus )
{
! int ret;
! pegasus->dr.requesttype = PEGASUS_REQT_WRITE;
! pegasus->dr.request = PEGASUS_REQ_SET_REGS;
! pegasus->dr.value = 0;
! pegasus->dr.index = cpu_to_le16(EthCtrl0);
! pegasus->dr.length = cpu_to_le16(3);
! pegasus->ctrl_urb.transfer_buffer_length = 3;
! FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
! usb_sndctrlpipe(pegasus->usb,0),
! (char *)&pegasus->dr,
! pegasus->eth_regs, 3, ctrl_callback, pegasus );
!
! if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
! err( __FUNCTION__ " BAD CTRL %d, flags %x",ret,pegasus->flags );
!
! return ret;
}
!
! static int read_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd )
{
! int i;
! __u8 data[4] = { phy, 0, 0, indx };
! __u16 regdi;
!
! set_register( pegasus, PhyCtrl, 0 );
! set_registers( pegasus, PhyAddr, sizeof(data), data );
! set_register( pegasus, PhyCtrl, (indx | PHY_READ) );
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, PhyCtrl, 1, data);
! if ( data[0] & PHY_DONE )
break;
}
! if ( i < REG_TIMEOUT ) {
! get_registers( pegasus, PhyData, 2, ®di );
*regd = le16_to_cpu(regdi);
! return 0;
}
! warn( __FUNCTION__ " failed" );
!
return 1;
}
! static int write_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd )
! {
! int i;
! __u8 data[4] = { phy, 0, 0, indx };
!
! *(data + 1) = cpu_to_le16p( ®d );
! set_register( pegasus, PhyCtrl, 0 );
! set_registers( pegasus, PhyAddr, 4, data );
! set_register( pegasus, PhyCtrl, (indx | PHY_WRITE) );
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, PhyCtrl, 1, data);
! if ( data[0] & PHY_DONE )
break;
}
! if ( i < REG_TIMEOUT )
! return 0;
! warn( __FUNCTION__ " failed" );
return 1;
}
!
! static int read_eprom_word( pegasus_t *pegasus, __u8 index, __u16 *retdata )
{
! int i;
__u8 tmp;
__u16 retdatai;
!
! set_register( pegasus, EpromCtrl, 0 );
! set_register( pegasus, EpromOffset, index );
! set_register( pegasus, EpromCtrl, EPROM_READ);
!
! for ( i=0; i < REG_TIMEOUT; i++ ) {
! get_registers( pegasus, EpromCtrl, 1, &tmp );
! if ( tmp & EPROM_DONE )
break;
}
! if ( i < REG_TIMEOUT ) {
! get_registers( pegasus, EpromData, 2, &retdatai );
! *retdata = le16_to_cpu (retdatai);
! return 0;
}
! warn( __FUNCTION__ " failed" );
return -1;
}
#ifdef PEGASUS_WRITE_EEPROM
! static inline void enable_eprom_write( pegasus_t *pegasus )
{
! __u8 tmp;
! get_registers( pegasus, EthCtrl2, 1, &tmp );
! set_register( pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE );
}
!
! static inline void disable_eprom_write( pegasus_t *pegasus )
{
! __u8 tmp;
! get_registers( pegasus, EthCtrl2, 1, &tmp );
! set_register( pegasus, EpromCtrl, 0 );
! set_register( pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE );
}
!
! static int write_eprom_word( pegasus_t *pegasus, __u8 index, __u16 data )
{
! int i, tmp;
! __u8 d[4] = {0x3f, 0, 0, EPROM_WRITE};
! set_registers( pegasus, EpromOffset, 4, d );
! enable_eprom_write( pegasus );
! set_register( pegasus, EpromOffset, index );
! set_registers( pegasus, EpromData, 2, &data );
! set_register( pegasus, EpromCtrl, EPROM_WRITE );
! for ( i=0; i < REG_TIMEOUT; i++ ) {
! get_registers( pegasus, EpromCtrl, 1, &tmp );
! if ( tmp & EPROM_DONE )
break;
}
! disable_eprom_write( pegasus );
! if ( i < REG_TIMEOUT )
! return 0;
! warn( __FUNCTION__ " failed" );
! return -1;
}
! #endif /* PEGASUS_WRITE_EEPROM */
! static inline void get_node_id( pegasus_t *pegasus, __u8 *id )
{
! int i;
__u16 w16;
!
for (i = 0; i < 3; i++) {
! read_eprom_word( pegasus, i, &w16);
! ((__u16 *) id)[i] = cpu_to_le16p (&w16);
}
}
!
! static void set_ethernet_addr( pegasus_t *pegasus )
{
! __u8 node_id[6];
get_node_id(pegasus, node_id);
! set_registers( pegasus, EthID, sizeof(node_id), node_id );
! memcpy( pegasus->net->dev_addr, node_id, sizeof(node_id) );
}
!
! static inline int reset_mac( pegasus_t *pegasus )
{
! __u8 data = 0x8;
! int i;
set_register(pegasus, EthCtrl1, data);
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, EthCtrl1, 1, &data);
if (~data & 0x08) {
! if (loopback & 1)
break;
! if ( mii_mode && (pegasus->features & HAS_HOME_PNA) )
! set_register( pegasus, Gpio1, 0x34 );
else
! set_register( pegasus, Gpio1, 0x26 );
! set_register( pegasus, Gpio0, pegasus->features );
! set_register( pegasus, Gpio0, DEFAULT_GPIO_SET );
break;
}
}
! if ( i == REG_TIMEOUT )
return 1;
! if ( usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
! usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK ) {
! __u16 auxmode;
!
! read_mii_word( pegasus, 0, 0x1b, &auxmode );
! write_mii_word( pegasus, 0, 0x1b, auxmode | 4 );
}
!
! return 0;
}
!
! static int enable_net_traffic( struct net_device *dev, struct usb_device *usb )
{
! __u16 linkpart, bmsr;
! __u8 data[4];
pegasus_t *pegasus = dev->priv;
!
! if ( read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr) )
! return 1;
! if ( !(bmsr & 0x20) && !loopback )
! warn( "%s: link NOT established (0x%x) - check the cable.",
! dev->name, bmsr );
! if ( read_mii_word(pegasus, pegasus->phy, MII_ANLPA, &linkpart) )
return 2;
! if ( !(linkpart & 1) )
! warn( "link partner stat %x", linkpart );
data[0] = 0xc9;
data[1] = 0;
! if ( linkpart & (ANLPA_100TX_FD | ANLPA_10T_FD) )
! data[1] |= 0x20; /* set full duplex */
! if ( linkpart & (ANLPA_100TX_FD | ANLPA_100TX_HD) )
! data[1] |= 0x10; /* set 100 Mbps */
! if ( mii_mode )
data[1] = 0;
data[2] = (loopback & 1) ? 0x09 : 0x01;
!
! memcpy( pegasus->eth_regs, data, sizeof(data) );
!
! set_registers( pegasus, EthCtrl0, 3, data );
return 0;
}
!
! static void read_bulk_callback( struct urb *urb )
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
int count = urb->actual_length, res;
int rx_status;
! struct sk_buff *skb;
__u16 pkt_len;
! if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
return;
net = pegasus->net;
! if ( !netif_device_present(net) )
return;
! if ( pegasus->flags & PEGASUS_RX_BUSY ) {
pegasus->stats.rx_errors++;
dbg("pegasus Rx busy");
return;
}
pegasus->flags |= PEGASUS_RX_BUSY;
! switch ( urb->status ) {
! case USB_ST_NOERROR:
! break;
! case USB_ST_NORESPONSE:
! dbg( "reset MAC" );
! pegasus->flags &= ~PEGASUS_RX_BUSY;
! break;
! default:
! dbg( "%s: RX status %d", net->name, urb->status );
! goto goon;
}
! if ( !count )
goto goon;
! rx_status = le32_to_cpu(*(int *)(pegasus->rx_buff + count - 4));
! if ( rx_status & 0x000e0000 ) {
dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
pegasus->stats.rx_errors++;
! if ( rx_status & 0x060000 )
pegasus->stats.rx_length_errors++;
! if ( rx_status & 0x080000 )
pegasus->stats.rx_crc_errors++;
! if ( rx_status & 0x100000 )
pegasus->stats.rx_frame_errors++;
goto goon;
}
pkt_len = (rx_status & 0xfff) - 8;
! if ( !(skb = dev_alloc_skb(pkt_len+2)) )
goto goon;
skb->dev = net;
***************
*** 547,646 ****
pegasus->stats.rx_bytes += pkt_len;
goon:
! FILL_BULK_URB(pegasus->rx_urb, pegasus->usb,
! usb_rcvbulkpipe(pegasus->usb, 1),
! pegasus->rx_buff, PEGASUS_MAX_MTU,
! read_bulk_callback, pegasus);
! if ((res = usb_submit_urb(pegasus->rx_urb)))
! warn("%s: failed submint rx_urb %d", __FUNCTION__, res);
pegasus->flags &= ~PEGASUS_RX_BUSY;
}
! static void write_bulk_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
! if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
return;
! if (!netif_device_present(pegasus->net))
return;
!
! if (urb->status)
info("%s: TX status %d", pegasus->net->name, urb->status);
pegasus->net->trans_start = jiffies;
! netif_wake_queue(pegasus->net);
}
#ifdef PEGASUS_USE_INTR
! static void intr_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
! __u8 *d;
! if (!pegasus)
return;
!
! switch (urb->status) {
! case 0:
! break;
! case -ENOENT:
! return;
! default:
! info("intr status %d", urb->status);
}
d = urb->transfer_buffer;
net = pegasus->net;
! if (d[0] & 0xfc) {
pegasus->stats.tx_errors++;
! if (d[0] & TX_UNDERRUN)
pegasus->stats.tx_fifo_errors++;
! if (d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT))
pegasus->stats.tx_aborted_errors++;
! if (d[0] & LATE_COL)
pegasus->stats.tx_window_errors++;
! if (d[0] & (NO_CARRIER | LOSS_CARRIER))
pegasus->stats.tx_carrier_errors++;
}
}
#endif
! static void pegasus_tx_timeout(struct net_device *net)
{
pegasus_t *pegasus = net->priv;
! if (!pegasus)
return;
!
warn("%s: Tx timed out.", net->name);
! pegasus->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
! usb_unlink_urb(pegasus->tx_urb);
pegasus->stats.tx_errors++;
}
! static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
{
! pegasus_t *pegasus = net->priv;
! int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3;
! int res;
__u16 l16 = skb->len;
!
! netif_stop_queue(net);
!
! ((__u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
! memcpy(pegasus->tx_buff + 2, skb->data, skb->len);
! FILL_BULK_URB(pegasus->tx_urb, pegasus->usb,
! usb_sndbulkpipe(pegasus->usb, 2),
! pegasus->tx_buff, PEGASUS_MAX_MTU,
! write_bulk_callback, pegasus);
! pegasus->tx_urb->transfer_buffer_length = count;
! if ((res = usb_submit_urb(pegasus->tx_urb))) {
warn("failed tx_urb %d", res);
pegasus->stats.tx_errors++;
! netif_start_queue(net);
} else {
pegasus->stats.tx_packets++;
pegasus->stats.tx_bytes += skb->len;
--- 569,670 ----
pegasus->stats.rx_bytes += pkt_len;
goon:
! FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb,
! usb_rcvbulkpipe(pegasus->usb, 1),
! pegasus->rx_buff, PEGASUS_MAX_MTU,
! read_bulk_callback, pegasus );
! if ( (res = usb_submit_urb(&pegasus->rx_urb)) )
! warn( __FUNCTION__ " failed submint rx_urb %d", res);
pegasus->flags &= ~PEGASUS_RX_BUSY;
}
!
! static void write_bulk_callback( struct urb *urb )
{
pegasus_t *pegasus = urb->context;
! if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
return;
! if ( !netif_device_present(pegasus->net) )
return;
!
! if ( urb->status )
info("%s: TX status %d", pegasus->net->name, urb->status);
pegasus->net->trans_start = jiffies;
! netif_wake_queue( pegasus->net );
}
#ifdef PEGASUS_USE_INTR
! static void intr_callback( struct urb *urb )
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
! __u8 *d;
! if ( !pegasus )
return;
!
! switch ( urb->status ) {
! case USB_ST_NOERROR:
! break;
! case USB_ST_URB_KILLED:
! return;
! default:
! info("intr status %d", urb->status);
}
d = urb->transfer_buffer;
net = pegasus->net;
! if ( d[0] & 0xfc ) {
pegasus->stats.tx_errors++;
! if ( d[0] & TX_UNDERRUN )
pegasus->stats.tx_fifo_errors++;
! if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
pegasus->stats.tx_aborted_errors++;
! if ( d[0] & LATE_COL )
pegasus->stats.tx_window_errors++;
! if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
pegasus->stats.tx_carrier_errors++;
}
}
#endif
! static void pegasus_tx_timeout( struct net_device *net )
{
pegasus_t *pegasus = net->priv;
! if ( !pegasus )
return;
!
warn("%s: Tx timed out.", net->name);
! pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK;
! usb_unlink_urb( &pegasus->tx_urb );
pegasus->stats.tx_errors++;
}
!
! static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net )
{
! pegasus_t *pegasus = net->priv;
! int count = ((skb->len+2) & 0x3f) ? skb->len+2 : skb->len+3;
! int res;
__u16 l16 = skb->len;
!
! netif_stop_queue( net );
!
! ((__u16 *)pegasus->tx_buff)[0] = cpu_to_le16( l16 );
! memcpy(pegasus->tx_buff+2, skb->data, skb->len);
! FILL_BULK_URB( &pegasus->tx_urb, pegasus->usb,
! usb_sndbulkpipe(pegasus->usb, 2),
! pegasus->tx_buff, PEGASUS_MAX_MTU,
! write_bulk_callback, pegasus );
! pegasus->tx_urb.transfer_buffer_length = count;
! if ((res = usb_submit_urb(&pegasus->tx_urb))) {
warn("failed tx_urb %d", res);
pegasus->stats.tx_errors++;
! netif_start_queue( net );
} else {
pegasus->stats.tx_packets++;
pegasus->stats.tx_bytes += skb->len;
***************
*** 652,866 ****
return 0;
}
! static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
{
! return &((pegasus_t *) dev->priv)->stats;
}
! static inline void disable_net_traffic(pegasus_t * pegasus)
{
! int tmp = 0;
! set_registers(pegasus, EthCtrl0, 2, &tmp);
}
! static inline void get_interrupt_interval(pegasus_t * pegasus)
{
! __u8 data[2];
! read_eprom_word(pegasus, 4, (__u16 *) data);
! if (data[1] < 0x80) {
! info("intr interval will be changed from %ums to %ums",
! data[1], 0x80);
data[1] = 0x80;
#ifdef PEGASUS_WRITE_EEPROM
! write_eprom_word(pegasus, 4, *(__u16 *) data);
#endif
}
pegasus->intr_interval = data[1];
}
- static void set_carrier(struct net_device *net)
- {
- pegasus_t *pegasus;
- short tmp;
-
- pegasus = net->priv;
- read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
- if (tmp & BMSR_LSTATUS)
- netif_carrier_on(net);
- else
- netif_carrier_off(net);
-
- }
static int pegasus_open(struct net_device *net)
{
! pegasus_t *pegasus = (pegasus_t *) net->priv;
! int res;
! down(&pegasus->sem);
! FILL_BULK_URB(pegasus->rx_urb, pegasus->usb,
! usb_rcvbulkpipe(pegasus->usb, 1),
! pegasus->rx_buff, PEGASUS_MAX_MTU,
! read_bulk_callback, pegasus);
! if ((res = usb_submit_urb(pegasus->rx_urb)))
! warn("%s: failed rx_urb %d", __FUNCTION__, res);
#ifdef PEGASUS_USE_INTR
! FILL_INT_URB(pegasus->intr_urb, pegasus->usb,
! usb_rcvintpipe(pegasus->usb, 3),
! pegasus->intr_buff, sizeof(pegasus->intr_buff),
! intr_callback, pegasus, pegasus->intr_interval);
! if ((res = usb_submit_urb(pegasus->intr_urb)))
! warn("%s: failed intr_urb %d", __FUNCTION__, res);
#endif
! netif_start_queue(net);
pegasus->flags |= PEGASUS_RUNNING;
- if ((res = enable_net_traffic(net, pegasus->usb))) {
- err("can't enable_net_traffic() - %d", res);
- res = -EIO;
- goto exit;
- }
-
- set_carrier(net);
- res = 0;
- exit:
- up(&pegasus->sem);
! return res;
}
! static int pegasus_close(struct net_device *net)
{
! pegasus_t *pegasus = net->priv;
- down(&pegasus->sem);
pegasus->flags &= ~PEGASUS_RUNNING;
! netif_stop_queue(net);
! if (!(pegasus->flags & PEGASUS_UNPLUG))
! disable_net_traffic(pegasus);
!
! usb_unlink_urb(pegasus->rx_urb);
! usb_unlink_urb(pegasus->tx_urb);
! usb_unlink_urb(pegasus->ctrl_urb);
#ifdef PEGASUS_USE_INTR
! usb_unlink_urb(pegasus->intr_urb);
#endif
- up(&pegasus->sem);
return 0;
}
! static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
{
! pegasus_t *pegasus;
! int cmd;
! char tmp[128];
!
! pegasus = net->priv;
! if (get_user(cmd, (int *) uaddr))
! return -EFAULT;
! switch (cmd) {
! case ETHTOOL_GDRVINFO:{
! struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
! strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
! strncpy(info.version, DRIVER_VERSION,
! ETHTOOL_BUSINFO_LEN);
! sprintf(tmp, "usb%d:%d", pegasus->usb->bus->busnum,
! pegasus->usb->devnum);
! strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
! if (copy_to_user(uaddr, &info, sizeof(info)))
! return -EFAULT;
! return 0;
! }
! case ETHTOOL_GSET:{
! struct ethtool_cmd ecmd;
! short lpa, bmcr;
!
! if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
! return -EFAULT;
! ecmd.supported = (SUPPORTED_10baseT_Half |
! SUPPORTED_10baseT_Full |
! SUPPORTED_100baseT_Half |
! SUPPORTED_100baseT_Full |
! SUPPORTED_Autoneg |
! SUPPORTED_TP | SUPPORTED_MII);
! ecmd.port = PORT_TP;
! ecmd.transceiver = XCVR_INTERNAL;
! ecmd.phy_address = pegasus->phy;
! read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
! read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
! if (bmcr & BMCR_ANENABLE) {
! ecmd.autoneg = AUTONEG_ENABLE;
! ecmd.speed = lpa & (LPA_100HALF | LPA_100FULL) ?
! SPEED_100 : SPEED_10;
! if (ecmd.speed == SPEED_100)
! ecmd.duplex = lpa & LPA_100FULL ?
! DUPLEX_FULL : DUPLEX_HALF;
! else
! ecmd.duplex = lpa & LPA_10FULL ?
! DUPLEX_FULL : DUPLEX_HALF;
! } else {
! ecmd.autoneg = AUTONEG_DISABLE;
! ecmd.speed = bmcr & BMCR_SPEED100 ?
! SPEED_100 : SPEED_10;
! ecmd.duplex = bmcr & BMCR_FULLDPLX ?
! DUPLEX_FULL : DUPLEX_HALF;
! }
! if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
! return -EFAULT;
return 0;
! }
! case ETHTOOL_SSET:{
! return -EOPNOTSUPP;
! }
! case ETHTOOL_GLINK:{
! struct ethtool_value edata = { ETHTOOL_GLINK };
! edata.data = netif_carrier_ok(net);
! if (copy_to_user(uaddr, &edata, sizeof(edata)))
! return -EFAULT;
return 0;
! }
! default:
! return -EOPNOTSUPP;
}
}
- static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
- {
- __u16 *data = (__u16 *) & rq->ifr_data;
- pegasus_t *pegasus = net->priv;
- int res;
-
- down(&pegasus->sem);
- switch (cmd) {
- case SIOCETHTOOL:
- res = pegasus_ethtool_ioctl(net, rq->ifr_data);
- break;
- case SIOCDEVPRIVATE:
- data[0] = pegasus->phy;
- case SIOCDEVPRIVATE + 1:
- read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]);
- res = 0;
- break;
- case SIOCDEVPRIVATE + 2:
- if (!capable(CAP_NET_ADMIN)) {
- up(&pegasus->sem);
- return -EPERM;
- }
- write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]);
- res = 0;
- break;
- default:
- res = -EOPNOTSUPP;
- }
- up(&pegasus->sem);
-
- return res;
- }
! static void pegasus_set_multicast(struct net_device *net)
{
pegasus_t *pegasus = net->priv;
--- 676,786 ----
return 0;
}
!
! static struct net_device_stats *pegasus_netdev_stats( struct net_device *dev )
{
! return &((pegasus_t *)dev->priv)->stats;
}
!
! static inline void disable_net_traffic( pegasus_t *pegasus )
{
! int tmp=0;
! set_registers( pegasus, EthCtrl0, 2, &tmp );
}
!
! static inline void get_interrupt_interval( pegasus_t *pegasus )
{
! __u8 data[2];
! read_eprom_word( pegasus, 4, (__u16 *)data );
! if ( data[1] < 0x80 ) {
! info( "intr interval will be changed from %ums to %ums",
! data[1], 0x80 );
data[1] = 0x80;
#ifdef PEGASUS_WRITE_EEPROM
! write_eprom_word( pegasus, 4, *(__u16 *)data );
#endif
}
pegasus->intr_interval = data[1];
}
static int pegasus_open(struct net_device *net)
{
! pegasus_t *pegasus = (pegasus_t *)net->priv;
! int res;
! if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
! err("can't enable_net_traffic() - %d", res);
! return -EIO;
! }
! FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb,
! usb_rcvbulkpipe(pegasus->usb, 1),
! pegasus->rx_buff, PEGASUS_MAX_MTU,
! read_bulk_callback, pegasus );
! if ( (res = usb_submit_urb(&pegasus->rx_urb)) )
! warn( __FUNCTION__ " failed rx_urb %d", res );
#ifdef PEGASUS_USE_INTR
! FILL_INT_URB( &pegasus->intr_urb, pegasus->usb,
! usb_rcvintpipe(pegasus->usb, 3),
! pegasus->intr_buff, sizeof(pegasus->intr_buff),
! intr_callback, pegasus, pegasus->intr_interval );
! if ( (res = usb_submit_urb(&pegasus->intr_urb)) )
! warn( __FUNCTION__ " failed intr_urb %d", res);
#endif
! netif_start_queue( net );
pegasus->flags |= PEGASUS_RUNNING;
! return 0;
}
!
! static int pegasus_close( struct net_device *net )
{
! pegasus_t *pegasus = net->priv;
pegasus->flags &= ~PEGASUS_RUNNING;
! netif_stop_queue( net );
! if ( !(pegasus->flags & PEGASUS_UNPLUG) )
! disable_net_traffic( pegasus );
!
! usb_unlink_urb( &pegasus->rx_urb );
! usb_unlink_urb( &pegasus->tx_urb );
! usb_unlink_urb( &pegasus->ctrl_urb );
#ifdef PEGASUS_USE_INTR
! usb_unlink_urb( &pegasus->intr_urb );
#endif
return 0;
}
!
! static int pegasus_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
{
! __u16 *data = (__u16 *)&rq->ifr_data;
! pegasus_t *pegasus = net->priv;
+ switch(cmd) {
+ case SIOCDEVPRIVATE:
+ data[0] = pegasus->phy;
+ case SIOCDEVPRIVATE+1:
+ read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]);
return 0;
! case SIOCDEVPRIVATE+2:
! if ( !capable(CAP_NET_ADMIN) )
! return -EPERM;
! write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]);
return 0;
! default:
! return -EOPNOTSUPP;
}
}
! static void pegasus_set_multicast( struct net_device *net )
{
pegasus_t *pegasus = net->priv;
***************
*** 870,876 ****
pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
info("%s: Promiscuous mode enabled", net->name);
} else if ((net->mc_count > multicast_filter_limit) ||
! (net->flags & IFF_ALLMULTI)) {
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
info("%s set allmulti", net->name);
--- 790,796 ----
pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
info("%s: Promiscuous mode enabled", net->name);
} else if ((net->mc_count > multicast_filter_limit) ||
! (net->flags & IFF_ALLMULTI)) {
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
info("%s set allmulti", net->name);
***************
*** 880,976 ****
}
pegasus->flags |= ETH_REGS_CHANGE;
! ctrl_callback(pegasus->ctrl_urb);
netif_wake_queue(net);
}
! static __u8 mii_phy_probe(pegasus_t * pegasus)
{
! int i;
! __u16 tmp;
! for (i = 0; i < 32; i++) {
! read_mii_word(pegasus, i, MII_BMSR, &tmp);
! if (tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0)
continue;
else
! return i;
}
! return 0xff;
}
! static inline void setup_pegasus_II(pegasus_t * pegasus)
{
! set_register(pegasus, Reg1d, 0);
! set_register(pegasus, Reg7b, 2);
! if (pegasus->features & HAS_HOME_PNA && mii_mode)
! set_register(pegasus, Reg81, 6);
else
! set_register(pegasus, Reg81, 2);
}
! static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
! const struct usb_device_id *id)
{
! struct net_device *net;
! pegasus_t *pegasus;
! int dev_index = id - pegasus_ids;
if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
err("usb_set_configuration() failed");
return NULL;
}
! if (!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) {
err("out of memory allocating device structure");
return NULL;
}
! usb_inc_dev_use(dev);
memset(pegasus, 0, sizeof(struct pegasus));
pegasus->dev_index = dev_index;
! init_waitqueue_head(&pegasus->ctrl_wait);
!
! pegasus->ctrl_urb = usb_alloc_urb(0);
! if (!pegasus->ctrl_urb) {
! kfree(pegasus);
! return NULL;
! }
! pegasus->rx_urb = usb_alloc_urb(0);
! if (!pegasus->rx_urb) {
! usb_free_urb(pegasus->ctrl_urb);
! kfree(pegasus);
! return NULL;
! }
! pegasus->tx_urb = usb_alloc_urb(0);
! if (!pegasus->tx_urb) {
! usb_free_urb(pegasus->rx_urb);
! usb_free_urb(pegasus->ctrl_urb);
! kfree(pegasus);
! return NULL;
! }
! pegasus->intr_urb = usb_alloc_urb(0);
! if (!pegasus->intr_urb) {
! usb_free_urb(pegasus->tx_urb);
! usb_free_urb(pegasus->rx_urb);
! usb_free_urb(pegasus->ctrl_urb);
! kfree(pegasus);
! return NULL;
! }
! net = init_etherdev(NULL, 0);
! if (!net) {
! usb_free_urb(pegasus->tx_urb);
! usb_free_urb(pegasus->rx_urb);
! usb_free_urb(pegasus->ctrl_urb);
! kfree(pegasus);
! return NULL;
}
!
! init_MUTEX(&pegasus->sem);
! down(&pegasus->sem);
pegasus->usb = dev;
pegasus->net = net;
SET_MODULE_OWNER(net);
--- 800,867 ----
}
pegasus->flags |= ETH_REGS_CHANGE;
! ctrl_callback( &pegasus->ctrl_urb );
netif_wake_queue(net);
}
!
! static __u8 mii_phy_probe( pegasus_t *pegasus )
{
! int i;
! __u16 tmp;
! for ( i=0; i < 32; i++ ) {
! read_mii_word( pegasus, i, MII_BMSR, &tmp );
! if ( tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0 )
continue;
else
! return i;
}
! return 0xff;
}
!
! static inline void setup_pegasus_II( pegasus_t *pegasus )
{
! set_register( pegasus, Reg1d, 0 );
! set_register( pegasus, Reg7b, 2 );
! if ( pegasus->features & HAS_HOME_PNA && mii_mode )
! set_register( pegasus, Reg81, 6 );
else
! set_register( pegasus, Reg81, 2 );
}
!
! static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum,
! const struct usb_device_id *id)
{
! struct net_device *net;
! pegasus_t *pegasus;
! int dev_index = id - pegasus_ids;
if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
err("usb_set_configuration() failed");
return NULL;
}
! if(!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) {
err("out of memory allocating device structure");
return NULL;
}
! usb_inc_dev_use( dev );
memset(pegasus, 0, sizeof(struct pegasus));
pegasus->dev_index = dev_index;
! init_waitqueue_head( &pegasus->ctrl_wait );
! net = init_etherdev( NULL, 0 );
! if ( !net ) {
! kfree( pegasus );
! return NULL;
}
!
pegasus->usb = dev;
pegasus->net = net;
SET_MODULE_OWNER(net);
***************
*** 987,1051 ****
pegasus->features = usb_dev_id[dev_index].private;
#ifdef PEGASUS_USE_INTR
! get_interrupt_interval(pegasus);
#endif
! if (reset_mac(pegasus)) {
err("can't reset MAC");
! unregister_netdev(pegasus->net);
! usb_free_urb(pegasus->tx_urb);
! usb_free_urb(pegasus->rx_urb);
! usb_free_urb(pegasus->ctrl_urb);
! kfree(pegasus->net);
kfree(pegasus);
pegasus = NULL;
! goto exit;
}
! info("%s: %s", net->name, usb_dev_id[dev_index].name);
! set_ethernet_addr(pegasus);
! if (pegasus->features & PEGASUS_II) {
! info("setup Pegasus II specific registers");
! setup_pegasus_II(pegasus);
! }
!
! pegasus->phy = mii_phy_probe(pegasus);
! if (pegasus->phy == 0xff) {
! warn("can't locate MII phy, using default");
pegasus->phy = 1;
}
- exit:
- up(&pegasus->sem);
return pegasus;
}
! static void pegasus_disconnect(struct usb_device *dev, void *ptr)
{
struct pegasus *pegasus = ptr;
! if (!pegasus) {
warn("unregistering non-existant device");
return;
}
pegasus->flags |= PEGASUS_UNPLUG;
! unregister_netdev(pegasus->net);
! usb_dec_dev_use(dev);
! usb_unlink_urb(pegasus->intr_urb);
! usb_unlink_urb(pegasus->tx_urb);
! usb_unlink_urb(pegasus->rx_urb);
! usb_unlink_urb(pegasus->ctrl_urb);
! usb_free_urb(pegasus->intr_urb);
! usb_free_urb(pegasus->tx_urb);
! usb_free_urb(pegasus->rx_urb);
! usb_free_urb(pegasus->ctrl_urb);
! kfree(pegasus->net);
! kfree(pegasus);
pegasus = NULL;
}
static struct usb_driver pegasus_driver = {
name: "pegasus",
probe: pegasus_probe,
--- 878,929 ----
pegasus->features = usb_dev_id[dev_index].private;
#ifdef PEGASUS_USE_INTR
! get_interrupt_interval( pegasus );
#endif
! if ( reset_mac(pegasus) ) {
err("can't reset MAC");
! unregister_netdev( pegasus->net );
kfree(pegasus);
pegasus = NULL;
! return NULL;
}
! info( "%s: %s", net->name, usb_dev_id[dev_index].name );
! set_ethernet_addr( pegasus );
! if ( pegasus->features & PEGASUS_II ) {
! info( "setup Pegasus II specific registers" );
! setup_pegasus_II( pegasus );
! }
!
! pegasus->phy = mii_phy_probe( pegasus );
! if ( pegasus->phy == 0xff ) {
! warn( "can't locate MII phy, using default" );
pegasus->phy = 1;
}
return pegasus;
}
!
! static void pegasus_disconnect( struct usb_device *dev, void *ptr )
{
struct pegasus *pegasus = ptr;
! if ( !pegasus ) {
warn("unregistering non-existant device");
return;
}
pegasus->flags |= PEGASUS_UNPLUG;
! unregister_netdev( pegasus->net );
! usb_dec_dev_use( dev );
! kfree( pegasus );
pegasus = NULL;
}
+
static struct usb_driver pegasus_driver = {
name: "pegasus",
probe: pegasus_probe,
***************
*** 1056,1068 ****
int __init pegasus_init(void)
{
info(DRIVER_VERSION ":" DRIVER_DESC);
! return usb_register(&pegasus_driver);
}
void __exit pegasus_exit(void)
{
! usb_deregister(&pegasus_driver);
}
! module_init(pegasus_init);
! module_exit(pegasus_exit);
--- 934,946 ----
int __init pegasus_init(void)
{
info(DRIVER_VERSION ":" DRIVER_DESC);
! return usb_register( &pegasus_driver );
}
void __exit pegasus_exit(void)
{
! usb_deregister( &pegasus_driver );
}
! module_init( pegasus_init );
! module_exit( pegasus_exit );
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pegasus.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pegasus.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pegasus.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pegasus.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,10 ****
/*
! * Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or modify
! * it under the terms of the GNU General Public License version 2 as published
! * by the Free Software Foundation.
*
*/
--- 1,19 ----
/*
! * Copyright (c) 1999,2000 Petko Manolov - Petkan (pmanolov@lnxw.com)
*
* This program is free software; you can redistribute it and/or modify
! * it under the terms of the GNU General Public License as published by
! * the Free Software Foundation; either version 2 of the License, or
! * (at your option) any later version.
*
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
***************
*** 22,27 ****
--- 31,44 ----
#define EPROM_WR_ENABLE 0x10
#define EPROM_LOAD 0x20
+ #define MII_BMCR 0x00
+ #define MII_BMSR 0x01
+ #define BMSR_MEDIA 0x7808
+ #define MII_ANLPA 0x05
+ #define ANLPA_100TX_FD 0x0100
+ #define ANLPA_100TX_HD 0x0080
+ #define ANLPA_10T_FD 0x0040
+ #define ANLPA_10T_HD 0x0020
#define PHY_DONE 0x80
#define PHY_READ 0x40
#define PHY_WRITE 0x20
***************
*** 57,62 ****
--- 74,80 ----
#define PEGASUS_REQ_GET_REGS 0xf0
#define PEGASUS_REQ_SET_REGS 0xf1
#define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS
+ #define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES)))
enum pegasus_registers {
EthCtrl0 = 0,
***************
*** 89,101 ****
unsigned features;
int dev_index;
int intr_interval;
! struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
! struct usb_ctrlrequest dr;
wait_queue_head_t ctrl_wait;
! struct semaphore sem;
! unsigned char rx_buff[PEGASUS_MAX_MTU];
! unsigned char tx_buff[PEGASUS_MAX_MTU];
! unsigned char intr_buff[8];
__u8 eth_regs[4];
__u8 phy;
__u8 gpio_res;
--- 107,119 ----
unsigned features;
int dev_index;
int intr_interval;
! struct urb ctrl_urb, rx_urb, tx_urb, intr_urb;
! devrequest dr;
wait_queue_head_t ctrl_wait;
! struct semaphore ctrl_sem;
! unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]);
! unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]);
! unsigned char ALIGN(intr_buff[8]);
__u8 eth_regs[4];
__u8 phy;
__u8 gpio_res;
***************
*** 113,128 ****
#define VENDOR_ABOCOM 0x07b8
#define VENDOR_ACCTON 0x083a
#define VENDOR_ADMTEK 0x07a6
- #define VENDOR_AEILAB 0x3334
#define VENDOR_ALLIEDTEL 0x07c9
#define VENDOR_BELKIN 0x050d
#define VENDOR_BILLIONTON 0x08dd
- #define VENDOR_COMPAQ 0x049f
#define VENDOR_COREGA 0x07aa
#define VENDOR_DLINK 0x2001
- #define VENDOR_ELCON 0x0db7
#define VENDOR_ELSA 0x05cc
- #define VENDOR_HAWKING 0x0e66
#define VENDOR_IODATA 0x04bb
#define VENDOR_KINGSTON 0x0951
#define VENDOR_LANEED 0x056e
--- 131,142 ----
***************
*** 131,137 ****
#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
! #define VENDOR_SIEMENS 0x067c
#else /* PEGASUS_DEV */
--- 145,151 ----
#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
!
#else /* PEGASUS_DEV */
***************
*** 159,176 ****
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
DEFAULT_GPIO_RESET )
- PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
- DEFAULT_GPIO_RESET )
PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
VENDOR_ADMTEK, 0x0986,
DEFAULT_GPIO_RESET | HAS_HOME_PNA )
- PEGASUS_DEV( "ADMtek AN986A USB MAC", VENDOR_ADMTEK, 0x1986,
- DEFAULT_GPIO_RESET | PEGASUS_II )
- PEGASUS_DEV( "AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701,
- DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
--- 173,184 ----
***************
*** 179,194 ****
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
DEFAULT_GPIO_RESET | HAS_HOME_PNA )
- PEGASUS_DEV( "iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511,
- DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004,
DEFAULT_GPIO_RESET )
- PEGASUS_DEV( "Corega FEter", VENDOR_COREGA, 0x000d,
- DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
LINKSYS_GPIO_RESET )
PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002,
--- 187,198 ----
***************
*** 203,218 ****
DEFAULT_GPIO_RESET | HAS_HOME_PNA )
PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1,
DEFAULT_GPIO_RESET )
- PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002,
- DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
DEFAULT_GPIO_RESET )
- PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
- DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
DEFAULT_GPIO_RESET )
- PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
- DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
DEFAULT_GPIO_RESET)
PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
--- 207,216 ----
***************
*** 245,257 ****
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
DEFAULT_GPIO_RESET )
- PEGASUS_DEV( "SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
- DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET )
! PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
! DEFAULT_GPIO_RESET | PEGASUS_II )
! PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
! DEFAULT_GPIO_RESET | PEGASUS_II )
#endif /* PEGASUS_DEV */
--- 243,250 ----
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET )
!
#endif /* PEGASUS_DEV */
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/printer.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/printer.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/printer.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/printer.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,12 ****
/*
! * printer.c Version 0.11
*
* Copyright (c) 1999 Michael Gee
* Copyright (c) 1999 Pavel Machek
* Copyright (c) 2000 Randy Dunlap
* Copyright (c) 2000 Vojtech Pavlik
- # Copyright (c) 2001 Pete Zaitcev
- # Copyright (c) 2001 David Paschal
*
* USB Printer Device Class driver for USB printers and printer cables
*
--- 1,10 ----
/*
! * printer.c Version 0.8
*
* Copyright (c) 1999 Michael Gee
* Copyright (c) 1999 Pavel Machek
* Copyright (c) 2000 Randy Dunlap
* Copyright (c) 2000 Vojtech Pavlik
*
* USB Printer Device Class driver for USB printers and printer cables
*
***************
*** 19,29 ****
* v0.4 - fixes in unidirectional mode
* v0.5 - add DEVICE_ID string support
* v0.6 - never time out
! * v0.7 - fixed bulk-IN read and poll (David Paschal)
* v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths
- * v0.10 - add proto_bias option (Pete Zaitcev)
- * v0.11 - add hpoj.sourceforge.net ioctls (David Paschal)
*/
/*
--- 17,25 ----
* v0.4 - fixes in unidirectional mode
* v0.5 - add DEVICE_ID string support
* v0.6 - never time out
! * v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
* v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths
*/
/*
***************
*** 58,93 ****
/*
* Version Information
*/
! #define DRIVER_VERSION "v0.11"
! #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024
! /* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
- #define IOCNR_GET_DEVICE_ID 1
- #define IOCNR_GET_PROTOCOLS 2
- #define IOCNR_SET_PROTOCOL 3
- #define IOCNR_HP_SET_CHANNEL 4
- #define IOCNR_GET_BUS_ADDRESS 5
- #define IOCNR_GET_VID_PID 6
- /* Get device_id string: */
- #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
- /* The following ioctls were added for http://hpoj.sourceforge.net: */
- /* Get two-int array:
- * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
- * [1]=supported protocol mask (mask&(1<dev);
- dbg("devfs=0x%p", usblp->devfs);
- dbg("buf=0x%p", usblp->buf);
- dbg("readcount=%d", usblp->readcount);
- dbg("ifnum=%d", usblp->ifnum);
- for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
- dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
- dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
- dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
- }
- dbg("current_protocol=%d", usblp->current_protocol);
- dbg("minor=%d", usblp->minor);
- dbg("quirks=%d", usblp->quirks);
- dbg("used=%d", usblp->used);
- dbg("bidir=%d", usblp->bidir);
- dbg("device_id_string=\"%s\"",
- usblp->device_id_string ?
- usblp->device_id_string + 2 :
- (unsigned char *)"(null)");
- }
- #endif
-
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usblp *usblp_table[USBLP_MINORS];
--- 102,107 ----
***************
*** 188,239 ****
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
- { 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */
- { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */
- { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */
- { 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */
- { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
- { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
- { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
- { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
{ 0, 0 }
};
- static int usblp_select_alts(struct usblp *usblp);
- static int usblp_set_protocol(struct usblp *usblp, int protocol);
- static int usblp_cache_device_id_string(struct usblp *usblp);
-
-
/*
* Functions for usblp control messages.
*/
! static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
{
int retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
! request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
request, !!dir, recip, value, len, retval);
return retval < 0 ? retval : 0;
}
#define usblp_read_status(usblp, status)\
! usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
#define usblp_get_id(usblp, config, id, maxlen)\
! usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
#define usblp_reset(usblp)\
! usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
!
! #define usblp_hp_channel_change_request(usblp, channel, buffer) \
! usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
!
! /*
! * See the description for usblp_select_alts() below for the usage
! * explanation. Look into your /proc/bus/usb/devices and dmesg in
! * case of any trouble.
! */
! static int proto_bias = -1;
/*
* URB callback.
--- 123,151 ----
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
{ 0, 0 }
};
/*
* Functions for usblp control messages.
*/
! static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len)
{
int retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
! request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5);
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
request, !!dir, recip, value, len, retval);
return retval < 0 ? retval : 0;
}
#define usblp_read_status(usblp, status)\
! usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
#define usblp_get_id(usblp, config, id, maxlen)\
! usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
#define usblp_reset(usblp)\
! usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
/*
* URB callback.
***************
*** 257,263 ****
* Get and print printer errors.
*/
! static char *usblp_messages[] = { "ok", "out of paper", "off-line", "unknown error" };
static int usblp_check_status(struct usblp *usblp, int err)
{
--- 169,175 ----
* Get and print printer errors.
*/
! static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
static int usblp_check_status(struct usblp *usblp, int err)
{
***************
*** 345,364 ****
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
! info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb.transfer_buffer);
kfree (usblp->device_id_string);
kfree (usblp);
}
- static void usblp_unlink_urbs(struct usblp *usblp)
- {
- usb_unlink_urb(&usblp->writeurb);
- if (usblp->bidir)
- usb_unlink_urb(&usblp->readurb);
- }
-
static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
--- 257,269 ----
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
! info ("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb.transfer_buffer);
kfree (usblp->device_id_string);
kfree (usblp);
}
static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
***************
*** 367,373 ****
lock_kernel();
usblp->used = 0;
if (usblp->dev) {
! usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
--- 272,280 ----
lock_kernel();
usblp->used = 0;
if (usblp->dev) {
! if (usblp->bidir)
! usb_unlink_urb(&usblp->readurb);
! usb_unlink_urb(&usblp->writeurb);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
***************
*** 387,396 ****
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
! int length, err, i;
! unsigned char lpstatus, newChannel;
! int status;
! int twoints[2];
int retval = 0;
down (&usblp->sem);
--- 294,301 ----
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
! int length, err;
! unsigned char status;
int retval = 0;
down (&usblp->sem);
***************
*** 409,536 ****
goto done;
}
! length = usblp_cache_device_id_string(usblp);
! if (length < 0) {
! retval = length;
! goto done;
! }
! if (length > _IOC_SIZE(cmd))
! length = _IOC_SIZE(cmd); /* truncate */
!
! if (copy_to_user((unsigned char *) arg,
! usblp->device_id_string,
! (unsigned long) length)) {
! retval = -EFAULT;
! goto done;
! }
!
! break;
!
! case IOCNR_GET_PROTOCOLS:
! if (_IOC_DIR(cmd) != _IOC_READ ||
! _IOC_SIZE(cmd) < sizeof(twoints)) {
! retval = -EINVAL;
! goto done;
! }
!
! twoints[0] = usblp->current_protocol;
! twoints[1] = 0;
! for (i = USBLP_FIRST_PROTOCOL;
! i <= USBLP_LAST_PROTOCOL; i++) {
! if (usblp->protocol[i].alt_setting >= 0)
! twoints[1] |= (1<current_protocol);
! }
! break;
!
! case IOCNR_HP_SET_CHANNEL:
! if (_IOC_DIR(cmd) != _IOC_WRITE ||
! usblp->dev->descriptor.idVendor != 0x03F0 ||
! usblp->quirks & USBLP_QUIRK_BIDIR) {
! retval = -EINVAL;
! goto done;
! }
!
! err = usblp_hp_channel_change_request(usblp,
! arg, &newChannel);
if (err < 0) {
! err("usblp%d: error = %d setting "
! "HP channel",
usblp->minor, err);
retval = -EIO;
goto done;
}
! dbg("usblp%d requested/got HP channel %ld/%d",
! usblp->minor, arg, newChannel);
! break;
!
! case IOCNR_GET_BUS_ADDRESS:
! if (_IOC_DIR(cmd) != _IOC_READ ||
! _IOC_SIZE(cmd) < sizeof(twoints)) {
! retval = -EINVAL;
! goto done;
! }
!
! twoints[0] = usblp->dev->bus->busnum;
! twoints[1] = usblp->dev->devnum;
! if (copy_to_user((unsigned char *)arg,
! (unsigned char *)twoints,
! sizeof(twoints))) {
! retval = -EFAULT;
! goto done;
! }
! dbg("usblp%d is bus=%d, device=%d",
! usblp->minor, twoints[0], twoints[1]);
! break;
! case IOCNR_GET_VID_PID:
! if (_IOC_DIR(cmd) != _IOC_READ ||
! _IOC_SIZE(cmd) < sizeof(twoints)) {
! retval = -EINVAL;
! goto done;
! }
! twoints[0] = usblp->dev->descriptor.idVendor;
! twoints[1] = usblp->dev->descriptor.idProduct;
! if (copy_to_user((unsigned char *)arg,
! (unsigned char *)twoints,
! sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
- dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
- usblp->minor, twoints[0], twoints[1]);
break;
default:
--- 314,345 ----
goto done;
}
! err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
if (err < 0) {
! dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
usblp->minor, err);
+ usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
retval = -EIO;
goto done;
}
! length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
! if (length < DEVICE_ID_SIZE)
! usblp->device_id_string[length] = '\0';
! else
! usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
! dbg ("usblp%d Device ID string [%d/max %d]='%s'",
! usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]);
! if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */
! if (copy_to_user((unsigned char *) arg,
! usblp->device_id_string, (unsigned long) length)) {
retval = -EFAULT;
goto done;
}
break;
default:
***************
*** 540,552 ****
switch (cmd) {
case LPGETSTATUS:
! if (usblp_read_status(usblp, &lpstatus)) {
err("usblp%d: failed reading printer status", usblp->minor);
retval = -EIO;
goto done;
}
! status = lpstatus;
! if (copy_to_user ((int *)arg, &status, sizeof(int)))
retval = -EFAULT;
break;
--- 349,360 ----
switch (cmd) {
case LPGETSTATUS:
! if (usblp_read_status(usblp, &status)) {
err("usblp%d: failed reading printer status", usblp->minor);
retval = -EIO;
goto done;
}
! if (copy_to_user ((unsigned char *)arg, &status, 1))
retval = -EFAULT;
break;
***************
*** 562,569 ****
static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
! int timeout, err = 0;
! size_t writecount = 0;
while (writecount < count) {
--- 370,376 ----
static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
! int timeout, err = 0, writecount = 0;
while (writecount < count) {
***************
*** 619,628 ****
(count - writecount) : USBLP_BUF_SIZE;
if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount,
! usblp->writeurb.transfer_buffer_length)) {
! up(&usblp->sem);
! return writecount ? writecount : -EFAULT;
! }
usblp->writeurb.dev = usblp->dev;
usb_submit_urb(&usblp->writeurb);
--- 426,432 ----
(count - writecount) : USBLP_BUF_SIZE;
if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount,
! usblp->writeurb.transfer_buffer_length)) return -EFAULT;
usblp->writeurb.dev = usblp->dev;
usb_submit_urb(&usblp->writeurb);
***************
*** 741,996 ****
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
! struct usblp *usblp = 0;
! int protocol;
char name[6];
! /* Malloc and start initializing usblp structure so we can use it
! * directly. */
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
! err("out of memory for usblp");
! goto abort;
}
memset(usblp, 0, sizeof(struct usblp));
- usblp->dev = dev;
init_MUTEX (&usblp->sem);
! init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum;
! /* Look for a free usblp_table entry. */
! while (usblp_table[usblp->minor]) {
! usblp->minor++;
! if (usblp->minor >= USBLP_MINORS) {
! err("no more free usblp devices");
! goto abort;
! }
}
- /* Malloc device ID string buffer to the largest expected length,
- * since we can re-query it on an ioctl and a dynamic string
- * could change in length. */
if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
! err("out of memory for device_id_string");
! goto abort;
}
! /* Malloc write/read buffers in one chunk. We somewhat wastefully
! * malloc both regardless of bidirectionality, because the
! * alternate setting can be changed later via an ioctl. */
! if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
! err("out of memory for buf");
! goto abort;
! }
!
! /* Lookup quirks for this printer. */
! usblp->quirks = usblp_quirks(
! dev->descriptor.idVendor,
! dev->descriptor.idProduct);
!
! /* Analyze and pick initial alternate settings and endpoints. */
! protocol = usblp_select_alts(usblp);
! if (protocol < 0) {
! dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
! dev->descriptor.idVendor,
! dev->descriptor.idProduct);
! goto abort;
! }
!
! /* Setup the selected alternate setting and endpoints. */
! if (usblp_set_protocol(usblp, protocol) < 0)
! goto abort;
! /* Retrieve and store the device ID string. */
! usblp_cache_device_id_string(usblp);
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
! usblp_table[usblp->minor] = usblp;
! /* If we have devfs, create with perms=660. */
! sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
! USBLP_MINOR_BASE + usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
! info("usblp%d: USB %sdirectional printer dev %d "
! "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
! usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
! usblp->protocol[usblp->current_protocol].alt_setting,
! usblp->current_protocol, usblp->dev->descriptor.idVendor,
! usblp->dev->descriptor.idProduct);
!
! return usblp;
!
! abort:
! if (usblp) {
! if (usblp->buf) kfree(usblp->buf);
! if (usblp->device_id_string) kfree(usblp->device_id_string);
! kfree(usblp);
! }
! return NULL;
! }
! /*
! * We are a "new" style driver with usb_device_id table,
! * but our requirements are too intricate for simple match to handle.
! *
! * The "proto_bias" option may be used to specify the preferred protocol
! * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
! * supports the preferred protocol, then we bind to it.
! *
! * The best interface for us is 7/1/2, because it is compatible
! * with a stream of characters. If we find it, we bind to it.
! *
! * Note that the people from hpoj.sourceforge.net need to be able to
! * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
! *
! * Failing 7/1/2, we look for 7/1/3, even though it's probably not
! * stream-compatible, because this matches the behaviour of the old code.
! *
! * If nothing else, we bind to 7/1/1 - the unidirectional interface.
! */
! static int usblp_select_alts(struct usblp *usblp)
! {
! struct usb_interface *if_alt;
! struct usb_interface_descriptor *ifd;
! struct usb_endpoint_descriptor *epd, *epwrite, *epread;
! int p, i, e;
!
! if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
!
! for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
! usblp->protocol[p].alt_setting = -1;
!
! /* Find out what we have. */
! for (i = 0; i < if_alt->num_altsetting; i++) {
! ifd = &if_alt->altsetting[i];
!
! if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
! continue;
!
! if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
! ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
! continue;
!
! /* Look for bulk OUT and IN endpoints. */
! epwrite = epread = 0;
! for (e = 0; e < ifd->bNumEndpoints; e++) {
! epd = &ifd->endpoint[e];
!
! if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
! USB_ENDPOINT_XFER_BULK)
! continue;
!
! if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
! if (!epwrite) epwrite=epd;
!
! } else {
! if (!epread) epread=epd;
! }
! }
!
! /* Ignore buggy hardware without the right endpoints. */
! if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
! continue;
!
! /* Turn off reads for 7/1/1 (unidirectional) interfaces
! * and buggy bidirectional printers. */
! if (ifd->bInterfaceProtocol == 1) {
! epread = NULL;
! } else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
! info("Disabling reads from problem bidirectional "
! "printer on usblp%d", usblp->minor);
! epread = NULL;
! }
!
! usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
! usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
! usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
! }
!
! /* If our requested protocol is supported, then use it. */
! if (proto_bias >= USBLP_FIRST_PROTOCOL &&
! proto_bias <= USBLP_LAST_PROTOCOL &&
! usblp->protocol[proto_bias].alt_setting != -1)
! return proto_bias;
!
! /* Ordering is important here. */
! if (usblp->protocol[2].alt_setting != -1) return 2;
! if (usblp->protocol[1].alt_setting != -1) return 1;
! if (usblp->protocol[3].alt_setting != -1) return 3;
!
! /* If nothing is available, then don't bind to this device. */
! return -1;
! }
!
! static int usblp_set_protocol(struct usblp *usblp, int protocol)
! {
! int r, alts;
!
! if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
! return -EINVAL;
!
! alts = usblp->protocol[protocol].alt_setting;
! if (alts < 0) return -EINVAL;
! r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
! if (r < 0) {
! err("can't set desired altsetting %d on interface %d",
! alts, usblp->ifnum);
! return r;
! }
!
! FILL_BULK_URB(&usblp->writeurb, usblp->dev,
! usb_sndbulkpipe(usblp->dev,
! usblp->protocol[protocol].epwrite->bEndpointAddress),
! usblp->buf, 0,
! usblp_bulk, usblp);
!
! usblp->bidir = (usblp->protocol[protocol].epread != 0);
! if (usblp->bidir)
! FILL_BULK_URB(&usblp->readurb, usblp->dev,
! usb_rcvbulkpipe(usblp->dev,
! usblp->protocol[protocol].epread->bEndpointAddress),
! usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
! usblp_bulk, usblp);
!
! usblp->current_protocol = protocol;
! dbg("usblp%d set protocol %d", usblp->minor, protocol);
! return 0;
! }
!
! /* Retrieves and caches device ID string.
! * Returns length, including length bytes but not null terminator.
! * On error, returns a negative errno value. */
! static int usblp_cache_device_id_string(struct usblp *usblp)
! {
! int err, length;
!
! err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
! if (err < 0) {
! dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
! usblp->minor, err);
! usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
! return -EIO;
! }
!
! /* First two bytes are length in big-endian.
! * They count themselves, and we copy them into
! * the user's buffer. */
! length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
! if (length < 2)
! length = 2;
! else if (length >= DEVICE_ID_SIZE)
! length = DEVICE_ID_SIZE - 1;
! usblp->device_id_string[length] = '\0';
!
! dbg("usblp%d Device ID string [len=%d]=\"%s\"",
! usblp->minor, length, &usblp->device_id_string[2]);
!
! return length;
}
static void usblp_disconnect(struct usb_device *dev, void *ptr)
--- 545,681 ----
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
! struct usb_interface_descriptor *interface;
! struct usb_endpoint_descriptor *epread, *epwrite;
! struct usblp *usblp;
! int minor, i, bidir = 0, quirks;
! int alts = dev->actconfig->interface[ifnum].act_altsetting;
! int length, err;
! char *buf;
char name[6];
! /* If a bidirectional interface exists, use it. */
! for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
!
! interface = &dev->actconfig->interface[ifnum].altsetting[i];
!
! if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
! interface->bInterfaceProtocol < 1 || interface->bInterfaceProtocol > 3 ||
! (interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2))
! continue;
!
! if (interface->bInterfaceProtocol > 1) {
! bidir = 1;
! alts = i;
! break;
! }
! }
!
! interface = &dev->actconfig->interface[ifnum].altsetting[alts];
! if (usb_set_interface(dev, ifnum, alts))
! err("can't set desired altsetting %d on interface %d", alts, ifnum);
!
! epwrite = interface->endpoint + 0;
! epread = bidir ? interface->endpoint + 1 : NULL;
!
! if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
! if (interface->bNumEndpoints == 1)
! return NULL;
! epwrite = interface->endpoint + 1;
! epread = bidir ? interface->endpoint + 0 : NULL;
! }
!
! if ((epwrite->bEndpointAddress & 0x80) == 0x80)
! return NULL;
!
! if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
! return NULL;
!
! for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
! if (usblp_table[minor]) {
! err("no more free usblp devices");
! return NULL;
! }
!
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
! err("out of memory");
! return NULL;
}
memset(usblp, 0, sizeof(struct usblp));
init_MUTEX (&usblp->sem);
!
! /* lookup quirks for this printer */
! quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
!
! if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
! bidir = 0;
! epread = NULL;
! info ("Disabling reads from problem bidirectional printer on usblp%d",
! minor);
! }
!
! usblp->dev = dev;
usblp->ifnum = ifnum;
+ usblp->minor = minor;
+ usblp->bidir = bidir;
+ usblp->quirks = quirks;
! init_waitqueue_head(&usblp->wait);
!
! if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
! err("out of memory");
! kfree(usblp);
! return NULL;
}
if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
! err("out of memory");
! kfree(usblp);
! kfree(buf);
! return NULL;
}
! FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
! buf, 0, usblp_bulk, usblp);
! if (bidir)
! FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
! buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
!
! /* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */
! err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
! if (err >= 0) {
! length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
! if (length < DEVICE_ID_SIZE)
! usblp->device_id_string[length] = '\0';
! else
! usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
! dbg ("usblp%d Device ID string [%d]=%s",
! minor, length, &usblp->device_id_string[2]);
! }
! else {
! err ("usblp%d: error = %d reading IEEE-1284 Device ID string",
! minor, err);
! usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
! }
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
! sprintf(name, "lp%d", minor);
!
! /* if we have devfs, create with perms=660 */
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
! USBLP_MINOR_BASE + minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
! info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
! minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
! return usblp_table[minor] = usblp;
}
static void usblp_disconnect(struct usb_device *dev, void *ptr)
***************
*** 1006,1012 ****
lock_kernel();
usblp->dev = NULL;
! usblp_unlink_urbs(usblp);
if (!usblp->used)
usblp_cleanup (usblp);
--- 691,699 ----
lock_kernel();
usblp->dev = NULL;
! usb_unlink_urb(&usblp->writeurb);
! if (usblp->bidir)
! usb_unlink_urb(&usblp->readurb);
if (!usblp->used)
usblp_cleanup (usblp);
***************
*** 1040,1046 ****
{
if (usb_register(&usblp_driver))
return -1;
! info(DRIVER_VERSION ": " DRIVER_DESC);
return 0;
}
--- 727,733 ----
{
if (usb_register(&usblp_driver))
return -1;
! info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
***************
*** 1054,1059 ****
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
- MODULE_PARM(proto_bias, "i");
- MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
MODULE_LICENSE("GPL");
--- 741,745 ----
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
+
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-ctrl.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-ctrl.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-ctrl.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-ctrl.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,7 ****
/* Driver for Philips webcam
Functions that send various control messages to the webcam, including
video modes.
! (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,7 ----
/* Driver for Philips webcam
Functions that send various control messages to the webcam, including
video modes.
! (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 78,89 ****
#define READ_SHUTTER_FORMATTER 0x0600
#define READ_RED_GAIN_FORMATTER 0x0700
#define READ_BLUE_GAIN_FORMATTER 0x0800
- #define SENSOR_TYPE_FORMATTER1 0x0C00
#define READ_RAW_Y_MEAN_FORMATTER 0x3100
#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
#define MIRROR_IMAGE_FORMATTER 0x3300
#define LED_FORMATTER 0x3400
- #define SENSOR_TYPE_FORMATTER2 0x3700
/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
--- 78,87 ----
***************
*** 164,184 ****
/****************************************************************************/
- #define SendControlMsg(request, value, buflen) \
- usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
- request, \
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
- value, \
- pdev->vcinterface, \
- &buf, buflen, HZ / 2)
-
- #define RecvControlMsg(request, value, buflen) \
- usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
- request, \
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
- value, \
- pdev->vcinterface, \
- &buf, buflen, HZ / 2)
#if PWC_DEBUG
--- 162,167 ----
***************
*** 258,264 ****
ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0)
return ret;
! if (pEntry->compressed && pdev->decompressor != NULL)
pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
/* Set various parameters */
--- 241,247 ----
ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0)
return ret;
! if (pEntry->compressed)
pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
/* Set various parameters */
***************
*** 928,934 ****
int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
! GET_CHROM_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_RED_GAIN_FORMATTER,
pdev->vcinterface,
--- 911,917 ----
int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
! GET_STATUS_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_RED_GAIN_FORMATTER,
pdev->vcinterface,
***************
*** 967,973 ****
int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
! GET_CHROM_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_BLUE_GAIN_FORMATTER,
pdev->vcinterface,
--- 950,956 ----
int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
! GET_STATUS_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_BLUE_GAIN_FORMATTER,
pdev->vcinterface,
***************
*** 979,985 ****
return (buf << 8);
}
-
/* The following two functions are different, since they only read the
internal red/blue gains, which may be different from the manual
gains set or read above.
--- 962,967 ----
***************
*** 1015,1096 ****
&buf, 1, HZ / 2);
if (ret < 0)
! return ret;
return (buf << 8);
}
-
- static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
- {
- unsigned char buf;
-
- /* useful range is 0x01..0x20 */
- buf = speed / 0x7f0;
- return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
- SET_CHROM_CTL,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- AWB_CONTROL_SPEED_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- }
-
- static inline int pwc_get_wb_speed(struct pwc_device *pdev)
- {
- unsigned char buf;
- int ret;
-
- ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_CHROM_CTL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- AWB_CONTROL_SPEED_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
- return (buf * 0x7f0);
- }
-
-
- static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
- {
- unsigned char buf;
-
- /* useful range is 0x01..0x3F */
- buf = (delay >> 10);
- return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
- SET_CHROM_CTL,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- AWB_CONTROL_DELAY_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- }
-
- static inline int pwc_get_wb_delay(struct pwc_device *pdev)
- {
- unsigned char buf;
- int ret;
-
- ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_CHROM_CTL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- AWB_CONTROL_DELAY_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
- return (buf << 10);
- }
-
-
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
unsigned char buf[2];
if (pdev->type < 730)
return 0;
- on_value /= 100;
- off_value /= 100;
if (on_value < 0)
on_value = 0;
if (on_value > 0xff)
--- 997,1013 ----
&buf, 1, HZ / 2);
if (ret < 0)
! return ret;
return (buf << 8);
}
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
unsigned char buf[2];
if (pdev->type < 730)
return 0;
if (on_value < 0)
on_value = 0;
if (on_value > 0xff)
***************
*** 1131,1377 ****
if (ret < 0)
return ret;
! *on_value = buf[0] * 100;
! *off_value = buf[1] * 100;
return 0;
}
- static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
- {
- unsigned char buf;
- int ret;
-
- if (contour < 0)
- buf = 0xff; /* auto contour on */
- else
- buf = 0x0; /* auto contour off */
- ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
- SET_LUM_CTL,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- AUTO_CONTOUR_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
-
- if (contour < 0)
- return 0;
- if (contour > 0xffff)
- contour = 0xffff;
-
- buf = (contour >> 10); /* contour preset is [0..3f] */
- ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
- SET_LUM_CTL,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- PRESET_CONTOUR_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
- return 0;
- }
-
- static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
- {
- unsigned char buf;
- int ret;
-
- ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_LUM_CTL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- AUTO_CONTOUR_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
-
- if (buf == 0) {
- /* auto mode off, query current preset value */
- ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_LUM_CTL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- PRESET_CONTOUR_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
- *contour = (buf << 10);
- }
- else
- *contour = -1;
- return 0;
- }
-
-
- static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
- {
- unsigned char buf;
-
- if (backlight)
- buf = 0xff;
- else
- buf = 0x0;
- return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
- SET_LUM_CTL,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- BACK_LIGHT_COMPENSATION_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- }
-
- static inline int pwc_get_backlight(struct pwc_device *pdev)
- {
- int ret;
- unsigned char buf;
-
- ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_LUM_CTL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- BACK_LIGHT_COMPENSATION_FORMATTER,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
- return buf;
- }
-
-
- static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
- {
- unsigned char buf;
-
- if (flicker)
- buf = 0xff;
- else
- buf = 0x0;
- return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
- }
-
- static inline int pwc_get_flicker(struct pwc_device *pdev)
- {
- int ret;
- unsigned char buf;
-
- ret = RecvControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
- if (ret < 0)
- return ret;
- return buf;
- }
-
-
- static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
- {
- unsigned char buf;
-
- if (noise < 0)
- noise = 0;
- if (noise > 3)
- noise = 3;
- buf = noise;
- return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
- }
-
- static inline int pwc_get_dynamic_noise(struct pwc_device *pdev)
- {
- int ret;
- unsigned char buf;
-
- ret = RecvControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
- if (ret < 0)
- return ret;
- Debug("pwc_get_dynamic_noise = %d\n", buf);
- return buf;
- }
-
-
- int pwc_get_cmos_sensor(struct pwc_device *pdev)
- {
- unsigned char buf;
- int ret = -1, request;
-
- if (pdev->type < 675)
- request = SENSOR_TYPE_FORMATTER1;
- else if (pdev->type < 730)
- return -1; /* The Vesta series doesn't have this call */
- else
- request = SENSOR_TYPE_FORMATTER2;
-
- ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_STATUS_CTL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- request,
- pdev->vcinterface,
- &buf, 1, HZ / 2);
- if (ret < 0)
- return ret;
- if (pdev->type < 675)
- return buf | 0x100;
- else
- return buf;
- }
-
-
/* End of Add-Ons */
/* ************************************************* */
int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
- int ret = 0;
-
switch(cmd) {
case VIDIOCPWCRUSER:
{
if (pwc_restore_user(pdev))
! ret = -EINVAL;
break;
}
case VIDIOCPWCSUSER:
{
if (pwc_save_user(pdev))
! ret = -EINVAL;
break;
}
case VIDIOCPWCFACTORY:
{
if (pwc_restore_factory(pdev))
! ret = -EINVAL;
break;
}
case VIDIOCPWCSCQUAL:
{
! int qual;
if (copy_from_user(&qual, arg, sizeof(int)))
! ret = -EFAULT;
! else {
! if (qual < 0 || qual > 3)
! ret = -EINVAL;
! else
! ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);
! if (ret >= 0)
! pdev->vcompression = qual;
! }
break;
}
case VIDIOCPWCGCQUAL:
{
if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))
! ret = -EFAULT;
! break;
! }
!
! case VIDIOCPWCPROBE:
! {
! struct pwc_probe probe;
!
! strcpy(probe.name, pdev->vdev->name);
! probe.type = pdev->type;
! if (copy_to_user(arg, &probe, sizeof(probe)))
! ret = -EFAULT;
break;
}
--- 1048,1105 ----
if (ret < 0)
return ret;
! *on_value = buf[0];
! *off_value = buf[1];
return 0;
}
/* End of Add-Ons */
/* ************************************************* */
int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
switch(cmd) {
case VIDIOCPWCRUSER:
{
if (pwc_restore_user(pdev))
! return -EINVAL;
break;
}
case VIDIOCPWCSUSER:
{
if (pwc_save_user(pdev))
! return -EINVAL;
break;
}
case VIDIOCPWCFACTORY:
{
if (pwc_restore_factory(pdev))
! return -EINVAL;
break;
}
case VIDIOCPWCSCQUAL:
{
! int qual, ret;
if (copy_from_user(&qual, arg, sizeof(int)))
! return -EFAULT;
!
! if (qual < 0 || qual > 3)
! return -EINVAL;
! ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);
! if (ret < 0)
! return ret;
! pdev->vcompression = qual;
break;
}
case VIDIOCPWCGCQUAL:
{
if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))
! return -EFAULT;
break;
}
***************
*** 1380,1389 ****
int agc;
if (copy_from_user(&agc, arg, sizeof(agc)))
! ret = -EFAULT;
else {
if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))
! ret = -EINVAL;
}
break;
}
--- 1108,1117 ----
int agc;
if (copy_from_user(&agc, arg, sizeof(agc)))
! return -EFAULT;
else {
if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))
! return -EINVAL;
}
break;
}
***************
*** 1393,1428 ****
int agc;
if (pwc_get_agc(pdev, &agc))
! ret = -EINVAL;
! else
! if (copy_to_user(arg, &agc, sizeof(agc)))
! ret = -EFAULT;
break;
}
case VIDIOCPWCSSHUTTER:
{
! int shutter_speed;
if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))
! ret = -EFAULT;
! else
ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);
break;
}
case VIDIOCPWCSAWB:
{
struct pwc_whitebalance wb;
if (copy_from_user(&wb, arg, sizeof(wb)))
! ret = -EFAULT;
! else {
! ret = pwc_set_awb(pdev, wb.mode);
! if (ret >= 0 && wb.mode == PWC_WB_MANUAL) {
! pwc_set_red_gain(pdev, wb.manual_red);
! pwc_set_blue_gain(pdev, wb.manual_blue);
! }
}
break;
}
--- 1121,1162 ----
int agc;
if (pwc_get_agc(pdev, &agc))
! return -EINVAL;
! if (copy_to_user(arg, &agc, sizeof(agc)))
! return -EFAULT;
break;
}
case VIDIOCPWCSSHUTTER:
{
! int shutter_speed, ret;
if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))
! return -EFAULT;
! else {
ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);
+ if (ret < 0)
+ return ret;
+ }
break;
}
+
+ /* ************************************************* */
+ /* Begin of Add-Ons for color compensation */
+
case VIDIOCPWCSAWB:
{
struct pwc_whitebalance wb;
+ int ret;
if (copy_from_user(&wb, arg, sizeof(wb)))
! return -EFAULT;
!
! ret = pwc_set_awb(pdev, wb.mode);
! if (ret >= 0 && wb.mode == PWC_WB_MANUAL) {
! pwc_set_red_gain(pdev, wb.manual_red);
! pwc_set_blue_gain(pdev, wb.manual_blue);
}
break;
}
***************
*** 1434,1609 ****
memset(&wb, 0, sizeof(wb));
wb.mode = pwc_get_awb(pdev);
if (wb.mode < 0)
! ret = -EINVAL;
! else {
! if (wb.mode == PWC_WB_MANUAL) {
! wb.manual_red = pwc_get_red_gain(pdev);
! wb.manual_blue = pwc_get_blue_gain(pdev);
! }
! if (wb.mode == PWC_WB_AUTO) {
! wb.read_red = pwc_read_red_gain(pdev);
! wb.read_blue = pwc_read_blue_gain(pdev);
! }
! if (copy_to_user(arg, &wb, sizeof(wb)))
! ret= -EFAULT;
}
break;
}
-
- case VIDIOCPWCSAWBSPEED:
- {
- struct pwc_wb_speed wbs;
-
- if (copy_from_user(&wbs, arg, sizeof(wbs)))
- ret = -EFAULT;
- else {
- if (wbs.control_speed > 0) {
- ret = pwc_set_wb_speed(pdev, wbs.control_speed);
- }
- if (wbs.control_delay > 0) {
- ret = pwc_set_wb_delay(pdev, wbs.control_delay);
- }
- }
- break;
- }
-
- case VIDIOCPWCGAWBSPEED:
- {
- struct pwc_wb_speed wbs;
-
- ret = pwc_get_wb_speed(pdev);
- if (ret < 0)
- break;
- wbs.control_speed = ret;
- ret = pwc_get_wb_delay(pdev);
- if (ret < 0)
- break;
- wbs.control_delay = ret;
- if (copy_to_user(arg, &wbs, sizeof(wbs)))
- ret = -EFAULT;
- break;
- }
case VIDIOCPWCSLED:
{
struct pwc_leds leds;
if (copy_from_user(&leds, arg, sizeof(leds)))
! ret = -EFAULT;
! else
! ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);
! break;
}
case VIDIOCPWCGLED:
{
struct pwc_leds leds;
! ret = pwc_get_leds(pdev, &leds.led_on, &leds.led_off);
! if (ret < 0)
! break;
if (copy_to_user(arg, &leds, sizeof(leds)))
! ret = -EFAULT;
! break;
! }
!
! case VIDIOCPWCSCONTOUR:
! {
! int contour;
!
! if (copy_from_user(&contour, arg, sizeof(contour)))
! ret = -EFAULT;
! else
! ret = pwc_set_contour(pdev, contour);
! break;
! }
!
! case VIDIOCPWCGCONTOUR:
! {
! int contour;
!
! ret = pwc_get_contour(pdev, &contour);
! if (ret < 0)
! break;
!
! if (copy_to_user(arg, &contour, sizeof(contour)))
! ret = -EFAULT;
! break;
! }
!
! case VIDIOCPWCSBACKLIGHT:
! {
! int backlight;
!
! if (copy_from_user(&backlight, arg, sizeof(backlight)))
! ret = -EFAULT;
! else
! ret = pwc_set_backlight(pdev, backlight);
! break;
! }
!
! case VIDIOCPWCGBACKLIGHT:
! {
! ret = pwc_get_backlight(pdev);
! if (ret < 0)
! break;
! if (copy_to_user(arg, &ret, sizeof(ret)))
! ret = -EFAULT;
! break;
! }
!
! case VIDIOCPWCSFLICKER:
! {
! int flicker;
!
! if (copy_from_user(&flicker, arg, sizeof(flicker)))
! ret = -EFAULT;
! else
! ret = pwc_set_flicker(pdev, flicker);
break;
}
! case VIDIOCPWCGFLICKER:
! {
! ret = pwc_get_flicker(pdev);
! if (ret < 0)
! break;
! if (copy_to_user(arg, &ret, sizeof(ret)))
! ret = -EFAULT;
! break;
! }
!
! case VIDIOCPWCSDYNNOISE:
! {
! int dynnoise;
!
! if (copy_from_user(&dynnoise, arg, sizeof(dynnoise)))
! ret = -EFAULT;
! else
! ret = pwc_set_dynamic_noise(pdev, dynnoise);
! break;
! }
!
! case VIDIOCPWCGDYNNOISE:
! {
! ret = pwc_get_dynamic_noise(pdev);
! if (ret < 0)
! break;
! if (copy_to_user(arg, &ret, sizeof(ret)))
! ret = -EFAULT;
! break;
! }
!
default:
! ret = -ENOIOCTLCMD;
break;
}
!
! if (ret > 0)
! return 0;
! return ret;
}
--- 1168,1220 ----
memset(&wb, 0, sizeof(wb));
wb.mode = pwc_get_awb(pdev);
if (wb.mode < 0)
! return -EINVAL;
! wb.manual_red = pwc_get_red_gain(pdev);
! wb.manual_blue = pwc_get_blue_gain(pdev);
! if (wb.mode == PWC_WB_AUTO) {
! wb.read_red = pwc_read_red_gain(pdev);
! wb.read_blue = pwc_read_blue_gain(pdev);
}
break;
}
case VIDIOCPWCSLED:
{
+ int ret;
struct pwc_leds leds;
if (copy_from_user(&leds, arg, sizeof(leds)))
! return -EFAULT;
!
! ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);
! if (ret<0)
! return ret;
! break;
}
+
case VIDIOCPWCGLED:
{
+ int led;
struct pwc_leds leds;
! led = pwc_get_leds(pdev, &leds.led_on, &leds.led_off);
! if (led < 0)
! return -EINVAL;
if (copy_to_user(arg, &leds, sizeof(leds)))
! return -EFAULT;
break;
}
! /* End of Add-Ons */
! /* ************************************************* */
default:
! return -ENOIOCTLCMD;
break;
}
! return 0;
}
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-if.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-if.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-if.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-if.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,6 ****
/* Linux driver for Philips webcam
USB and Video4Linux interface part.
! (C) 1999-2002 Nemosoft Unv.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,6 ----
/* Linux driver for Philips webcam
USB and Video4Linux interface part.
! (C) 1999-2001 Nemosoft Unv.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 39,48 ****
/* Contributors:
- Alvarado: adding whitebalance code
! - Alistar Moire: QuickCam 3000 Pro device/product ID
! - Tony Hoyle: Creative Labs Webcam 5 device/product ID
! - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
! - Jk Fang: SOTEC device/product ID
*/
#include
--- 39,45 ----
/* Contributors:
- Alvarado: adding whitebalance code
! - Alistar Moire: QuickCam 3000 Pro testing
*/
#include
***************
*** 65,72 ****
/* Function prototypes and driver templates */
/* hotplug device table support */
! static struct usb_device_id pwc_device_table [] = {
! { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
{ USB_DEVICE(0x0471, 0x0303) },
{ USB_DEVICE(0x0471, 0x0304) },
{ USB_DEVICE(0x0471, 0x0307) },
--- 62,69 ----
/* Function prototypes and driver templates */
/* hotplug device table support */
! static __devinitdata struct usb_device_id pwc_device_table [] = {
! { USB_DEVICE(0x0471, 0x0302) },
{ USB_DEVICE(0x0471, 0x0303) },
{ USB_DEVICE(0x0471, 0x0304) },
{ USB_DEVICE(0x0471, 0x0307) },
***************
*** 75,88 ****
{ USB_DEVICE(0x0471, 0x0310) },
{ USB_DEVICE(0x0471, 0x0311) },
{ USB_DEVICE(0x0471, 0x0312) },
! { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
! { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech */
! { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
{ USB_DEVICE(0x055D, 0x9001) },
- { USB_DEVICE(0x041E, 0x400C) }, /* Creative */
- { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
- { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
- { USB_DEVICE(0x0d81, 0x1900) },
{ }
};
MODULE_DEVICE_TABLE(usb, pwc_device_table);
--- 72,81 ----
{ USB_DEVICE(0x0471, 0x0310) },
{ USB_DEVICE(0x0471, 0x0311) },
{ USB_DEVICE(0x0471, 0x0312) },
! { USB_DEVICE(0x069A, 0x0001) },
! { USB_DEVICE(0x046D, 0x08b0) },
! { USB_DEVICE(0x055D, 0x9000) },
{ USB_DEVICE(0x055D, 0x9001) },
{ }
};
MODULE_DEVICE_TABLE(usb, pwc_device_table);
***************
*** 107,113 ****
static int default_mbufs = 2; /* Default number of mmap() buffers */
int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
static int power_save = 0;
! static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
static struct {
int type;
--- 100,106 ----
static int default_mbufs = 2; /* Default number of mmap() buffers */
int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
static int power_save = 0;
! static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
static struct {
int type;
***************
*** 165,171 ****
succeeded. The pwc_device struct links back to both structures.
When a device is unplugged while in use it will be removed from the
! list of known USB devices; I also de-register it as a V4L device, but
unfortunately I can't free the memory since the struct is still in use
by the file descriptor. This free-ing is then deferend until the first
opportunity. Crude, but it works.
--- 158,164 ----
succeeded. The pwc_device struct links back to both structures.
When a device is unplugged while in use it will be removed from the
! list of known USB devices; I also de-register as a V4L device, but
unfortunately I can't free the memory since the struct is still in use
by the file descriptor. This free-ing is then deferend until the first
opportunity. Crude, but it works.
***************
*** 179,203 ****
/***************************************************************************/
/* Private functions */
/* Here we want the physical address of the memory.
! * This is used when initializing the contents of the area.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
! unsigned long kva, ret;
! kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
! kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva);
return ret;
}
! static void * rvmalloc(unsigned long size)
{
void * mem;
! unsigned long adr;
! size=PAGE_ALIGN(size);
mem=vmalloc_32(size);
if (mem)
{
--- 172,231 ----
/***************************************************************************/
/* Private functions */
+ /* Memory management functions, nicked from cpia.c, which nicked them from
+ bttv.c. So far, I've counted duplication of this code 6 times
+ (bttv, cpia, ibmcam, ov511, pwc, ieee1394).
+ */
+
+ /* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+ {
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if(pte_present(pte)) {
+ ret = (unsigned long) page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+
+ }
+ }
+ }
+ return ret;
+ }
+
+
+
/* Here we want the physical address of the memory.
! * This is used when initializing the contents of the
! * area and marking the pages as reserved.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
! unsigned long va, kva, ret;
! va = VMALLOC_VMADDR(adr);
! kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = __pa(kva);
return ret;
}
! static void * rvmalloc(signed long size)
{
void * mem;
! unsigned long adr, page;
! /* Round it off to PAGE_SIZE */
! size += (PAGE_SIZE - 1);
! size &= ~(PAGE_SIZE - 1);
!
mem=vmalloc_32(size);
if (mem)
{
***************
*** 205,211 ****
adr=(unsigned long) mem;
while (size > 0)
{
! mem_map_reserve(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
--- 233,240 ----
adr=(unsigned long) mem;
while (size > 0)
{
! page = kvirt_to_pa(adr);
! mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
***************
*** 213,228 ****
return mem;
}
! static void rvfree(void * mem, unsigned long size)
{
! unsigned long adr;
!
if (mem)
{
adr=(unsigned long) mem;
! while ((long) size > 0)
{
! mem_map_unreserve(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
--- 242,261 ----
return mem;
}
! static void rvfree(void * mem, signed long size)
{
! unsigned long adr, page;
!
! /* Round it off to PAGE_SIZE */
! size += (PAGE_SIZE - 1);
! size &= ~(PAGE_SIZE - 1);
if (mem)
{
adr=(unsigned long) mem;
! while (size > 0)
{
! page = kvirt_to_pa(adr);
! mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
***************
*** 313,320 ****
for (; i < MAX_IMAGES; i++)
pdev->image_ptr[i] = NULL;
- kbuf = NULL;
-
Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
return 0;
}
--- 346,351 ----
***************
*** 369,375 ****
rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
}
pdev->image_data = NULL;
-
Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
}
--- 400,405 ----
***************
*** 571,580 ****
pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
}
! /* 2001-10-14: YUV420P is the only palette remaining. */
static int pwc_set_palette(struct pwc_device *pdev, int pal)
{
! if ( pal == VIDEO_PALETTE_YUV420P
#if PWC_DEBUG
|| pal == VIDEO_PALETTE_RAW
#endif
--- 601,612 ----
pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
}
! /* 2001-10-14: The YUV420 is still there, but you can only set it from within
! a program (YUV420P being the default) */
static int pwc_set_palette(struct pwc_device *pdev, int pal)
{
! if ( pal == VIDEO_PALETTE_YUV420
! || pal == VIDEO_PALETTE_YUV420P
#if PWC_DEBUG
|| pal == VIDEO_PALETTE_RAW
#endif
***************
*** 592,598 ****
/* This gets called for the Isochronous pipe (video). This is done in
* interrupt time, so it has to be fast, not crash, and not stall. Neat.
*/
! static void pwc_isoc_handler(struct urb *urb)
{
struct pwc_device *pdev;
int i, fst, flen;
--- 624,630 ----
/* This gets called for the Isochronous pipe (video). This is done in
* interrupt time, so it has to be fast, not crash, and not stall. Neat.
*/
! static void pwc_isoc_handler(purb_t urb)
{
struct pwc_device *pdev;
int i, fst, flen;
***************
*** 754,760 ****
static int pwc_isoc_init(struct pwc_device *pdev)
{
struct usb_device *udev;
! struct urb *urb;
int i, j, ret;
struct usb_interface_descriptor *idesc;
--- 786,792 ----
static int pwc_isoc_init(struct pwc_device *pdev)
{
struct usb_device *udev;
! purb_t urb;
int i, j, ret;
struct usb_interface_descriptor *idesc;
***************
*** 855,861 ****
/* Stop camera, but only if we are sure the camera is still there */
if (!pdev->unplugged)
usb_set_interface(pdev->udev, 0, 0);
- /* Unlinking ISOC buffers one by one */
for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
pdev->sbuf[i].urb->next = NULL;
usb_unlink_urb(pdev->sbuf[i].urb);
--- 887,892 ----
***************
*** 868,873 ****
--- 899,905 ----
int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
{
int ret;
+
/* Stop isoc stuff */
pwc_isoc_cleanup(pdev);
/* Reset parameters */
***************
*** 930,958 ****
if (usb_set_interface(pdev->udev, 0, 0))
Info("Failed to set alternate interface to 0.\n");
pdev->usb_init = 1;
-
- if (pwc_trace & TRACE_OPEN) {
- /* Query CMOS sensor type */
- const char *sensor_type = NULL;
-
- i = pwc_get_cmos_sensor(pdev);
- switch(i) {
- case -1: /* Unknown, show nothing */; break;
- case 0x00: sensor_type = "Hyundai CMOS sensor"; break;
- case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break;
- case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break;
- case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break;
- case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break;
- case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
- case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break;
- case 0x40: sensor_type = "UPA 1021 sensor"; break;
- case 0x100: sensor_type = "VGA sensor"; break;
- case 0x101: sensor_type = "PAL MR sensor"; break;
- default: sensor_type = "unknown type of sensor"; break;
- }
- if (sensor_type != NULL)
- Info("Thes %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
- }
}
/* Turn on camera */
--- 962,967 ----
***************
*** 1484,1495 ****
*/
add_wait_queue(&pdev->frameq, &wait);
while (pdev->full_frames == NULL) {
- if (pdev->unplugged) {
- remove_wait_queue(&pdev->frameq, &wait);
- set_current_state(TASK_RUNNING);
- return -ENODEV;
- }
-
if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
--- 1493,1498 ----
***************
*** 1575,1581 ****
pdev = vdev->priv;
/* FIXME - audit mmap during a read */
- /* Nemo: 9 months and 20 kernel revisions later I still don't know what you mean by this :-) */
pos = (unsigned long)pdev->image_data;
while (size > 0) {
page = kvirt_to_pa(pos);
--- 1578,1583 ----
***************
*** 1607,1613 ****
int vendor_id, product_id, type_id;
int i, hint;
int video_nr = -1; /* default: use next available device */
! char serial_number[30], *name;
free_mem_leak();
--- 1609,1615 ----
int vendor_id, product_id, type_id;
int i, hint;
int video_nr = -1; /* default: use next available device */
! char serial_number[30];
free_mem_leak();
***************
*** 1628,1674 ****
switch (product_id) {
case 0x0302:
Info("Philips PCA645VC USB webcam detected.\n");
- name = "Philips 645 webcam";
type_id = 645;
break;
case 0x0303:
Info("Philips PCA646VC USB webcam detected.\n");
- name = "Philips 646 webcam";
type_id = 646;
break;
case 0x0304:
Info("Askey VC010 type 2 USB webcam detected.\n");
- name = "Askey VC010 webcam";
type_id = 646;
break;
case 0x0307:
Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
- name = "Philips 675 webcam";
type_id = 675;
break;
case 0x0308:
Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
- name = "Philips 680 webcam";
type_id = 680;
break;
case 0x030C:
Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
- name = "Philips 690 webcam";
type_id = 690;
break;
case 0x0310:
Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
- name = "Philips 730 webcam";
type_id = 730;
break;
case 0x0311:
Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
- name = "Philips 740 webcam";
type_id = 740;
break;
case 0x0312:
Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
- name = "Philips 750 webcam";
type_id = 750;
break;
default:
--- 1630,1667 ----
***************
*** 1680,1686 ****
switch(product_id) {
case 0x0001:
Info("Askey VC010 type 1 USB webcam detected.\n");
- name = "Askey VC010 webcam";
type_id = 645;
break;
default:
--- 1673,1678 ----
***************
*** 1691,1698 ****
else if (vendor_id == 0x046d) {
switch(product_id) {
case 0x08b0:
! Info("Logitech QuickCam 3000 Pro USB webcam detected.\n");
! name = "Logitech QuickCam 3000 Pro";
type_id = 730;
break;
default:
--- 1683,1689 ----
else if (vendor_id == 0x046d) {
switch(product_id) {
case 0x08b0:
! Info("Logitech QuickCam 3000 Pro detected.\n");
type_id = 730;
break;
default:
***************
*** 1708,1719 ****
switch(product_id) {
case 0x9000:
Info("Samsung MPC-C10 USB webcam detected.\n");
- name = "Samsung MPC-C10";
type_id = 675;
break;
case 0x9001:
Info("Samsung MPC-C30 USB webcam detected.\n");
- name = "Samsung MPC-C30";
type_id = 675;
break;
default:
--- 1699,1708 ----
***************
*** 1721,1769 ****
break;
}
}
! else if (vendor_id == 0x041e) {
! switch(product_id) {
! case 0x400c:
! Info("Creative Labs Webcam 5 detected.\n");
! name = "Creative Labs Webcam 5";
! type_id = 730;
! break;
! default:
! return NULL;
! break;
! }
! }
! else if (vendor_id == 0x04cc) {
! switch(product_id) {
! case 0x8116:
! Info("Sotec Afina Eye USB webcam detected.\n");
! name = "Sotec Afina Eye";
! type_id = 730;
! break;
! default:
! return NULL;
! break;
! }
! }
! else if (vendor_id == 0x0d81) {
! switch(product_id) {
! case 0x1900:
! Info("Visionite VCS-UC300 USB webcam detected.\n");
! name = "Visionite VCS-UC300";
! type_id = 740; /* CCD sensor */
! break;
! case 0x1910:
! Info("Visionite VCS-UM100 USB webcam detected.\n");
! name = "Visionite VCS-UM100";
! type_id = 730; /* CMOS sensor */
! break;
! default:
! return NULL;
! break;
! }
! }
! else
! return NULL; /* Not any of the know types; but the list keeps growing. */
memset(serial_number, 0, 30);
usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
--- 1710,1716 ----
break;
}
}
! else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
memset(serial_number, 0, 30);
usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
***************
*** 1797,1803 ****
return NULL;
}
memcpy(vdev, &pwc_template, sizeof(pwc_template));
! strcpy(vdev->name, name);
SET_MODULE_OWNER(vdev);
pdev->vdev = vdev;
vdev->priv = pdev;
--- 1744,1750 ----
return NULL;
}
memcpy(vdev, &pwc_template, sizeof(pwc_template));
! sprintf(vdev->name, "Philips %d webcam", pdev->type);
SET_MODULE_OWNER(vdev);
pdev->vdev = vdev;
vdev->priv = pdev;
***************
*** 1805,1810 ****
--- 1752,1758 ----
pdev->release = udev->descriptor.bcdDevice;
Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
/* Now search device_hint[] table for a match, so we can hint a node number. */
for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
***************
*** 1832,1837 ****
--- 1780,1795 ----
if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = pdev;
+ #if 0
+ /* Shut down camera now (some people like the LED off) */
+ if (power_save) {
+ Trace(TRACE_PROBE, "Powering down camera");
+ i = pwc_camera_power(pdev, 0);
+ if (i < 0)
+ Info("Failed to power-down the camera (%d)\n", i);
+ }
+ #endif
+
Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
return pdev;
}
***************
*** 1841,1847 ****
{
struct pwc_device *pdev;
int hint;
- DECLARE_WAITQUEUE(wait, current);
lock_kernel();
free_mem_leak();
--- 1799,1804 ----
***************
*** 1876,1894 ****
*/
wake_up(&pdev->frameq);
! /* Wait until we get a 'go' from _close(). This used
! to have a gigantic race condition, since we kfree()
stuff here, but we have to wait until close()
! is finished.
! */
Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
! add_wait_queue(&pdev->remove_ok, &wait);
! set_current_state(TASK_UNINTERRUPTIBLE);
! /* ... wait ... */
! schedule();
! remove_wait_queue(&pdev->remove_ok, &wait);
! set_current_state(TASK_RUNNING);
Trace(TRACE_PROBE, "Done sleeping.\n");
set_mem_leak(pdev->vdev);
pdev->vdev = NULL;
--- 1833,1845 ----
*/
wake_up(&pdev->frameq);
! /* Wait until we get a 'go' from _close(). This
! had a gigantic race condition, since we kfree()
stuff here, but we have to wait until close()
! is finished. */
Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
! sleep_on(&pdev->remove_ok);
Trace(TRACE_PROBE, "Done sleeping.\n");
set_mem_leak(pdev->vdev);
pdev->vdev = NULL;
***************
*** 1969,1980 ****
char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
! Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30,\n");
! Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
if (fps) {
! if (fps < 4 || fps > 30) {
! Err("Framerate out of bounds (4-30).\n");
return -EINVAL;
}
default_fps = fps;
--- 1920,1930 ----
char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
! Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro and the Samsung MPC-C10 and MPC-C30.\n");
if (fps) {
! if (fps < 5 || fps > 30) {
! Err("Framerate out of bounds (5-30).\n");
return -EINVAL;
}
default_fps = fps;
***************
*** 2026,2034 ****
if (power_save)
Info("Enabling power save on open/close.\n");
if (leds[0] >= 0)
! led_on = leds[0];
if (leds[1] >= 0)
! led_off = leds[1];
/* Big device node whoopla. Basicly, it allows you to assign a
device node (/dev/videoX) to a camera, based on its type
--- 1976,1984 ----
if (power_save)
Info("Enabling power save on open/close.\n");
if (leds[0] >= 0)
! led_on = leds[0] / 100;
if (leds[1] >= 0)
! led_off = leds[1] / 100;
/* Big device node whoopla. Basicly, it allows you to assign a
device node (/dev/videoX) to a camera, based on its type
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-ioctl.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-ioctl.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-ioctl.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-ioctl.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,7 ****
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
! /* (C) 2001-2002 Nemosoft Unv. webcam@smcc.demon.nl
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,7 ----
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
! /* (C) 2001 Nemosoft Unv. webcam@smcc.demon.nl
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 18,26 ****
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
! /* This is pwc-ioctl.h belonging to PWC 8.6 */
!
! /*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
--- 18,24 ----
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
! /*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
***************
*** 54,67 ****
#define PWC_FPS_SNAPSHOT 0x00400000
-
- struct pwc_probe
- {
- char name[32];
- int type;
- };
-
-
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
--- 52,57 ----
***************
*** 73,81 ****
Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
! When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined.
! 'read_red' and 'read_blue' are read-only.
*/
struct pwc_whitebalance
--- 63,71 ----
Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
! When mode == PWC_WB_MANUAL, manual_red and manual_blue are set or read;
otherwise undefined.
! read_red and read_blue are read-only.
*/
struct pwc_whitebalance
***************
*** 85,107 ****
int read_red, read_blue; /* R/O */
};
- /*
- 'control_speed' and 'control_delay' are used in automatic whitebalance mode,
- and tell the camera how fast it should react to changes in lighting, and
- with how much delay. Valid values are 0..65535.
- */
- struct pwc_wb_speed
- {
- int control_speed;
- int control_delay;
-
- };
/* Used with VIDIOCPWC[SG]LED */
struct pwc_leds
{
! int led_on; /* Led on-time; range = 0..25000 */
! int led_off; /* Led off-time; range = 0..25000 */
};
--- 75,86 ----
int read_red, read_blue; /* R/O */
};
/* Used with VIDIOCPWC[SG]LED */
struct pwc_leds
{
! int led_on; /* Led on-time; range = 0..255 */
! int led_off; /* */
};
***************
*** 125,143 ****
/* Get preferred compression quality */
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
-
- /* This is a probe function; since so many devices are supported, it
- becomes difficult to include all the names in programs that want to
- check for the enhanced Philips stuff. So in stead, try this PROBE;
- it returns a structure with the original name, and the corresponding
- Philips type.
- To use, fill the structure with zeroes, call PROBE and if that succeeds,
- compare the name with that returned from VIDIOCGCAP; they should be the
- same. If so, you can be assured it is a Philips (OEM) cam and the type
- is valid.
- */
- #define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
-
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
#define VIDIOCPWCSAGC _IOW('v', 200, int)
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
--- 104,109 ----
***************
*** 149,176 ****
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
! /* Auto WB speed */
! #define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
! #define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
!
! /* LEDs on/off/blink; int range 0..65535 */
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
- /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
- #define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
- #define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
-
- /* Backlight compensation; 0 = off, otherwise on */
- #define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
- #define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
-
- /* Flickerless mode; = 0 off, otherwise on */
- #define VIDIOCPWCSFLICKER _IOW('v', 208, int)
- #define VIDIOCPWCGFLICKER _IOR('v', 208, int)
-
- /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
- #define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
- #define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
-
#endif
--- 115,123 ----
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
! /* Turn LED on/off ; int range 0..65535 */
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
+ /* Get state of LED; int range 0..65535 */
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
#endif
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-misc.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-misc.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-misc.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-misc.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,6 ****
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
! (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,6 ----
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
! (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-uncompress.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-uncompress.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-uncompress.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-uncompress.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,6 ****
/* Linux driver for Philips webcam
Decompression frontend.
! (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,6 ----
/* Linux driver for Philips webcam
Decompression frontend.
! (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-uncompress.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-uncompress.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc-uncompress.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc-uncompress.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,4 ****
! /* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,4 ----
! /* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 20,27 ****
significant change should be reflected by increasing the
pwc_decompressor_version major number.
*/
! #ifndef PWC_UNCOMPRESS_H
! #define PWC_UNCOMPRESS_H
#include
#include
--- 20,27 ----
significant change should be reflected by increasing the
pwc_decompressor_version major number.
*/
! #ifndef PWC_DEC_H
! #define PWC_DEC_H
#include
#include
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/pwc.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/pwc.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,4 ****
! /* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,4 ----
! /* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 60,67 ****
/* Version block */
#define PWC_MAJOR 8
! #define PWC_MINOR 6
! #define PWC_VERSION "8.6"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
--- 60,67 ----
/* Version block */
#define PWC_MAJOR 8
! #define PWC_MINOR 4
! #define PWC_VERSION "8.4"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
***************
*** 96,102 ****
void *data;
int length;
int read;
! struct urb *urb;
};
/* intermediate buffers with raw data from the USB cam */
--- 96,102 ----
void *data;
int length;
int read;
! purb_t urb;
};
/* intermediate buffers with raw data from the USB cam */
***************
*** 247,253 ****
extern int pwc_set_saturation(struct pwc_device *pdev, int value);
extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
- extern int pwc_get_cmos_sensor(struct pwc_device *pdev);
/* Power down or up the camera; not supported by all models */
extern int pwc_camera_power(struct pwc_device *pdev, int power);
--- 247,252 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/rio500.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/rio500.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/rio500.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/rio500.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 141,147 ****
retval = -EFAULT;
goto err_out;
}
! if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) {
retval = -EINVAL;
goto err_out;
}
--- 141,147 ----
retval = -EFAULT;
goto err_out;
}
! if (rio_cmd.length > PAGE_SIZE) {
retval = -EINVAL;
goto err_out;
}
***************
*** 211,217 ****
retval = -EFAULT;
goto err_out;
}
! if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) {
retval = -EINVAL;
goto err_out;
}
--- 211,217 ----
retval = -EFAULT;
goto err_out;
}
! if (rio_cmd.length > PAGE_SIZE) {
retval = -EINVAL;
goto err_out;
}
HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb$B$@$1$KH/8+(B: rtl8150.c
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/scanner.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/scanner.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/scanner.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/scanner.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,13 ****
/* -*- linux-c -*- */
/*
! * Driver for USB Scanners (linux-2.4.18)
*
! * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
*
* Portions may be copyright Brad Keryan and Michael Gee.
*
! * Brian Beattie
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
--- 1,13 ----
/* -*- linux-c -*- */
/*
! * Driver for USB Scanners (linux-2.4.12)
*
! * Copyright (C) 1999, 2000, 2001 David E. Nelson
*
* Portions may be copyright Brad Keryan and Michael Gee.
*
! * David E. Nelson (dnelson@jump.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
***************
*** 300,323 ****
* Frank Zago and
* Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
*
- * 0.4.8 5/30/2002
- * - Added Mustek BearPaw 2400 TA. Thanks to Sergey
- * Vlasov .
- * - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's. These use
- * the Grandtech GT-6801 chip. Thanks to Henning
- * Meier-Geinitz .
- * - Increased Epson timeout to 60 secs as requested from
- * Karl Heinz Kremer .
- * - Changed maintainership from David E. Nelson to Brian
- * Beattie .
- *
* TODO
- * - Remove the 2/3 endpoint limitation
* - Performance
* - Select/poll methods
* - More testing
* - Proper registry/assignment for LM9830 ioctl's
- * - More general usage ioctl's
*
*
* Thanks to:
--- 300,310 ----
***************
*** 333,340 ****
* - All the folks who chimed in with reports and suggestions.
* - All the developers that are working on USB SANE backends or other
* applications to use USB scanners.
- * - Thanks to Greg KH for setting up Brian Beattie
- * to be the new USB Scanner maintainer.
*
* Performance:
*
--- 320,325 ----
***************
*** 762,768 ****
case SCANNER_IOCTL_CTRLMSG:
{
struct ctrlmsg_ioctl {
! struct usb_ctrlrequest req;
void *data;
} cmsg;
int pipe, nb, ret;
--- 747,753 ----
case SCANNER_IOCTL_CTRLMSG:
{
struct ctrlmsg_ioctl {
! devrequest req;
void *data;
} cmsg;
int pipe, nb, ret;
***************
*** 771,782 ****
if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
return -EFAULT;
! nb = cmsg.req.wLength;
if (nb > sizeof(buf))
return -EINVAL;
! if ((cmsg.req.bRequestType & 0x80) == 0) {
pipe = usb_sndctrlpipe(dev, 0);
if (nb > 0 && copy_from_user(buf, cmsg.data, nb))
return -EFAULT;
--- 756,767 ----
if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
return -EFAULT;
! nb = le16_to_cpup(&cmsg.req.length);
if (nb > sizeof(buf))
return -EINVAL;
! if ((cmsg.req.requesttype & 0x80) == 0) {
pipe = usb_sndctrlpipe(dev, 0);
if (nb > 0 && copy_from_user(buf, cmsg.data, nb))
return -EFAULT;
***************
*** 784,793 ****
pipe = usb_rcvctrlpipe(dev, 0);
}
! ret = usb_control_msg(dev, pipe, cmsg.req.bRequest,
! cmsg.req.bRequestType,
! cmsg.req.wValue,
! cmsg.req.wIndex,
buf, nb, HZ);
if (ret < 0) {
--- 769,778 ----
pipe = usb_rcvctrlpipe(dev, 0);
}
! ret = usb_control_msg(dev, pipe, cmsg.req.request,
! cmsg.req.requesttype,
! le16_to_cpup(&cmsg.req.value),
! le16_to_cpup(&cmsg.req.index),
buf, nb, HZ);
if (ret < 0) {
***************
*** 795,801 ****
return -EIO;
}
! if (nb > 0 && (cmsg.req.bRequestType & 0x80) && copy_to_user(cmsg.data, buf, nb))
return -EFAULT;
return 0;
--- 780,786 ----
return -EIO;
}
! if (nb > 0 && (cmsg.req.requesttype & 0x80) && copy_to_user(cmsg.data, buf, nb))
return -EFAULT;
return 0;
***************
*** 1032,1038 ****
switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
case 0x04b8: /* Seiko/Epson */
! scn->rd_nak_timeout = HZ * 60;
break;
case 0x055f: /* Mustek */
case 0x0400: /* Another Mustek */
--- 1017,1023 ----
switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
case 0x04b8: /* Seiko/Epson */
! scn->rd_nak_timeout = HZ * 40;
break;
case 0x055f: /* Mustek */
case 0x0400: /* Another Mustek */
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/scanner.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/scanner.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/scanner.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/scanner.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,9 ****
/*
! * Driver for USB Scanners (linux-2.4.18)
*
! * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
*
! * Brian Beattie
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
--- 1,9 ----
/*
! * Driver for USB Scanners (linux-2.4.12)
*
! * Copyright (C) 1999, 2000, 2001 David E. Nelson
*
! * David E. Nelson (dnelson@jump.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
***************
*** 48,54 ****
static __s32 vendor=-1, product=-1, read_timeout=0;
! MODULE_AUTHOR("Brian Beattie, beattie@beattie-home.net");
MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);
MODULE_LICENSE("GPL");
--- 48,54 ----
static __s32 vendor=-1, product=-1, read_timeout=0;
! MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);
MODULE_LICENSE("GPL");
***************
*** 90,101 ****
{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
/* Canon */
! { USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */
! { USB_DEVICE(0x04a9, 0x2204) }, /* CanoScan FB630U/FB636U */
! { USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */
! { USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */
! { USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */
{ USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
/* Colorado -- See Primax/Colorado below */
/* Epson -- See Seiko/Epson below */
/* Genius */
--- 90,98 ----
{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
/* Canon */
! { USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
{ USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
+ { USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
/* Colorado -- See Primax/Colorado below */
/* Epson -- See Seiko/Epson below */
/* Genius */
***************
*** 113,119 ****
{ USB_DEVICE(0x03f0, 0x0105) }, /* 4200C */
{ USB_DEVICE(0x03f0, 0x0305) }, /* 4300C */
{ USB_DEVICE(0x03f0, 0x0102) }, /* PhotoSmart S20 */
- { USB_DEVICE(0x03f0, 0x0705) }, /* 4400C */
{ USB_DEVICE(0x03f0, 0x0401) }, /* 5200C */
// { USB_DEVICE(0x03f0, 0x0701) }, /* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
{ USB_DEVICE(0x03f0, 0x0201) }, /* 6200C */
--- 110,115 ----
***************
*** 145,152 ****
{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
- { USB_DEVICE(0x055f, 0x0218) }, /* BearPaw 2400 TA */
- { USB_DEVICE(0x05d8, 0x4002) }, /* 1200 CU and 1200 UB Plus */
/* Plustek */
{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
{ USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */
--- 141,146 ----
***************
*** 185,196 ****
{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
{ USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */
{ USB_DEVICE(0x04b8, 0x010e) }, /* Expression 1680 */
- { USB_DEVICE(0x04b8, 0x010f) }, /* Perfection 1250U */
{ USB_DEVICE(0x04b8, 0x0110) }, /* Perfection 1650 */
{ USB_DEVICE(0x04b8, 0x0112) }, /* Perfection 2450 - GT-9700 for the Japanese mkt */
- { USB_DEVICE(0x04b8, 0x0114) }, /* Perfection 660 */
- { USB_DEVICE(0x04b8, 0x011b) }, /* Perfection 2400 Photo */
- { USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
/* Umax */
{ USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */
{ USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */
--- 179,186 ----
***************
*** 240,246 ****
#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
/* send/recv a control message to the scanner */
! #define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest )
#define SCN_MAX_MNR 16 /* We're allocated 16 minors */
--- 230,236 ----
#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
/* send/recv a control message to the scanner */
! #define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, devrequest )
#define SCN_MAX_MNR 16 /* We're allocated 16 minors */
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/se401.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/se401.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/se401.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/se401.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 41,52 ****
#include
#include
#include "se401.h"
static int flickerless=0;
static int video_nr = -1;
! static struct usb_device_id device_table [] = {
{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
--- 41,58 ----
#include
#include
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
+ #define virt_to_page(arg) MAP_NR(arg)
+ #define vmalloc_32 vmalloc
+ #endif
+
#include "se401.h"
static int flickerless=0;
static int video_nr = -1;
! #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
! static __devinitdata struct usb_device_id device_table [] = {
{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
***************
*** 56,61 ****
--- 62,68 ----
};
MODULE_DEVICE_TABLE(usb, device_table);
+ #endif
MODULE_AUTHOR("Jeroen Vreeken ");
MODULE_DESCRIPTION("SE401 USB Camera Driver");
***************
*** 73,89 ****
*
* Memory management
*
**********************************************************************/
/* Here we want the physical address of the memory.
! * This is used when initializing the contents of the area.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
! unsigned long kva, ret;
! kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
! kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva);
return ret;
}
--- 80,133 ----
*
* Memory management
*
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the ov511 driver -claudio
+ *
+ * Same for the se401 driver -Jeroen
**********************************************************************/
+ /* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+ {
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if (pte_present(pte)) {
+ ret = (unsigned long) page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+ }
+ }
+ }
+
+ return ret;
+ }
+
/* Here we want the physical address of the memory.
! * This is used when initializing the contents of the
! * area and marking the pages as reserved.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
! unsigned long va, kva, ret;
! va = VMALLOC_VMADDR(adr);
! kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = __pa(kva);
return ret;
}
***************
*** 91,99 ****
static void *rvmalloc(unsigned long size)
{
void *mem;
! unsigned long adr;
- size = PAGE_ALIGN(size);
mem = vmalloc_32(size);
if (!mem)
return NULL;
--- 135,146 ----
static void *rvmalloc(unsigned long size)
{
void *mem;
! unsigned long adr, page;
!
! /* Round it off to PAGE_SIZE */
! size += (PAGE_SIZE - 1);
! size &= ~(PAGE_SIZE - 1);
mem = vmalloc_32(size);
if (!mem)
return NULL;
***************
*** 101,109 ****
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem;
while (size > 0) {
! mem_map_reserve(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
! size -= PAGE_SIZE;
}
return mem;
--- 148,160 ----
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem;
while (size > 0) {
! page = kvirt_to_pa(adr);
! mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE;
! if (size > PAGE_SIZE)
! size -= PAGE_SIZE;
! else
! size = 0;
}
return mem;
***************
*** 111,126 ****
static void rvfree(void *mem, unsigned long size)
{
! unsigned long adr;
if (!mem)
return;
! adr = (unsigned long) mem;
! while ((long) size > 0) {
! mem_map_unreserve(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
! size -= PAGE_SIZE;
}
vfree(mem);
}
--- 162,184 ----
static void rvfree(void *mem, unsigned long size)
{
! unsigned long adr, page;
if (!mem)
return;
! size += (PAGE_SIZE - 1);
! size &= ~(PAGE_SIZE - 1);
!
! adr=(unsigned long) mem;
! while (size > 0) {
! page = kvirt_to_pa(adr);
! mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE;
! if (size > PAGE_SIZE)
! size -= PAGE_SIZE;
! else
! size = 0;
}
vfree(mem);
}
***************
*** 552,558 ****
*/
static int se401_start_stream(struct usb_se401 *se401)
{
! struct urb *urb;
int err=0, i;
se401->streaming=1;
--- 610,616 ----
*/
static int se401_start_stream(struct usb_se401 *se401)
{
! urb_t *urb;
int err=0, i;
se401->streaming=1;
***************
*** 588,594 ****
for (i=0; idev,
usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
--- 646,652 ----
for (i=0; idev,
usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
***************
*** 646,652 ****
return 0;
/* Check for a valid mode */
! if (width <= 0 || height <= 0)
return 1;
if ((width & 1) || (height & 1))
return 1;
--- 704,710 ----
return 0;
/* Check for a valid mode */
! if (!width || !height)
return 1;
if ((width & 1) || (height & 1))
return 1;
***************
*** 680,687 ****
static inline void enhance_picture(unsigned char *frame, int len)
{
while (len--) {
! *frame=(((*frame^255)*(*frame^255))/255)^255;
! frame++;
}
}
--- 738,744 ----
static inline void enhance_picture(unsigned char *frame, int len)
{
while (len--) {
! *frame++=(((*frame^255)*(*frame^255))/255)^255;
}
}
***************
*** 915,922 ****
/* Fix the top line */
framedata+=linelength;
for (i=0; icheight; i++) {
--- 972,978 ----
/* Fix the top line */
framedata+=linelength;
for (i=0; icheight; i++) {
***************
*** 1369,1381 ****
se401->sizes=cp[4]+cp[5]*256;
se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
- if (!se401->width)
- return 1;
se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
- if (!se401->height) {
- kfree(se401->width);
- return 1;
- }
for (i=0; isizes; i++) {
se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
--- 1425,1431 ----
***************
*** 1441,1448 ****
return 0;
}
! static void* se401_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
struct usb_se401 *se401;
--- 1491,1502 ----
return 0;
}
! #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
! static void* se401_probe(struct usb_device *dev, unsigned int ifnum)
! #else
! static void* __devinit se401_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
+ #endif
{
struct usb_interface_descriptor *interface;
struct usb_se401 *se401;
***************
*** 1571,1577 ****
--- 1625,1633 ----
static struct usb_driver se401_driver = {
name: "se401",
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
id_table: device_table,
+ #endif
probe: se401_probe,
disconnect: se401_disconnect
};
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/se401.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/se401.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/se401.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/se401.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 10,16 ****
#ifdef se401_DEBUG
# define PDEBUG(level, fmt, args...) \
! if (debug >= level) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
#else
# define PDEBUG(level, fmt, args...) do {} while(0)
#endif
--- 10,16 ----
#ifdef se401_DEBUG
# define PDEBUG(level, fmt, args...) \
! if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
#else
# define PDEBUG(level, fmt, args...) do {} while(0)
#endif
***************
*** 197,204 ****
char *fbuf; /* Videodev buffer area */
! struct urb *urb[SE401_NUMSBUF];
! struct urb *inturb;
int button;
int buttonpressed;
--- 197,204 ----
char *fbuf; /* Videodev buffer area */
! urb_t *urb[SE401_NUMSBUF];
! urb_t *inturb;
int button;
int buttonpressed;
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/Config.in LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/Config.in
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/Config.in 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/Config.in 2004-05-24 17:35:29.000000000 +0900
***************
*** 5,43 ****
comment 'USB Serial Converter support'
dep_tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
! if [ "$CONFIG_USB_SERIAL" != "n" ]; then
! dep_bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
! dep_mbool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC $CONFIG_USB_SERIAL
! dep_tristate ' USB Belkin and Peracom Single Port Serial Driver' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL
! dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL
! dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
! dep_tristate ' USB Empeg empeg-car Mark I/II Driver' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL
! dep_tristate ' USB FTDI Single Port Serial Driver' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL
! dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
! dep_tristate ' USB Compaq iPAQ / HP Jornada / Casio EM500 Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
! dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Inside Out Edgeport Serial Driver' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL
! dep_tristate ' USB Inside Out Edgeport Serial Driver (TI devices)' CONFIG_USB_SERIAL_EDGEPORT_TI $CONFIG_USB_SERIAL
! dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Keyspan USA-xxx Serial Driver' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL
! if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then
! bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28
! bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X
! bool ' USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA
! bool ' USB Keyspan USA-28XB Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XB
! bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
! bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
! bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
! bool ' USB Keyspan USA-19QW Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19QW
! bool ' USB Keyspan USA-19QI Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19QI
! bool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
! fi
! dep_tristate ' USB MCT Single Port Serial Driver' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL
! dep_tristate ' USB KL5KUSB105 (Palmconnect) Driver' CONFIG_USB_SERIAL_KLSI $CONFIG_USB_SERIAL
! dep_tristate ' USB Prolific 2303 Single Port Serial Driver' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL
! dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
! dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
! dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
fi
endmenu
--- 5,36 ----
comment 'USB Serial Converter support'
dep_tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
! if [ "$CONFIG_USB_SERIAL" = "y" ]; then
! dep_mbool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
fi
+ dep_mbool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC $CONFIG_USB_SERIAL
+ dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
+ dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+ dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_mbool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-28XB Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XB $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
+ dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
endmenu
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/Makefile LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/Makefile
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/Makefile 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/Makefile 2004-05-24 17:35:29.000000000 +0900
***************
*** 8,14 ****
obj-$(CONFIG_USB_SERIAL) += usbserial.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
- obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
--- 8,13 ----
***************
*** 20,31 ****
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
- obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
! obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
!
# Objects that export symbols.
export-objs := usbserial.o
--- 19,28 ----
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
!
# Objects that export symbols.
export-objs := usbserial.o
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/belkin_sa.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/belkin_sa.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/belkin_sa.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/belkin_sa.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 1,8 ****
/*
* Belkin USB Serial Adapter Driver
*
! * Copyright (C) 2000 William Greathouse (wgreathouse@smva.com)
! * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
--- 1,8 ----
/*
* Belkin USB Serial Adapter Driver
*
! * Copyright (C) 2000
! * William Greathouse (wgreathouse@smva.com)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
***************
*** 24,32 ****
* -- Add support for flush commands
* -- Add everything that is missing :)
*
- * 27-Nov-2001 gkh
- * compressed all the differnent device entries into 1.
- *
* 30-May-2001 gkh
* switched from using spinlock to a semaphore, which fixes lots of problems.
*
--- 24,29 ----
***************
*** 65,79 ****
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
- #include
#include
#ifdef CONFIG_USB_SERIAL_DEBUG
--- 62,79 ----
#include
#include
+ #include
+ #include
#include
+ #include
#include
#include
+ #include
#include
#include
#include
#include
#include
#include
#ifdef CONFIG_USB_SERIAL_DEBUG
***************
*** 88,94 ****
/*
* Version Information
*/
! #define DRIVER_VERSION "v1.2"
#define DRIVER_AUTHOR "William Greathouse "
#define DRIVER_DESC "USB Belkin Serial converter driver"
--- 88,94 ----
/*
* Version Information
*/
! #define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "William Greathouse "
#define DRIVER_DESC "USB Belkin Serial converter driver"
***************
*** 103,137 ****
static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
! static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
- { USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) },
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
! /* All of the device info needed for the serial converters */
! static struct usb_serial_device_type belkin_device = {
! .owner = THIS_MODULE,
! .name = "Belkin / Peracom / GoHubs USB Serial Adapter",
! .id_table = id_table_combined,
! .num_interrupt_in = 1,
! .num_bulk_in = 1,
! .num_bulk_out = 1,
! .num_ports = 1,
! .open = belkin_sa_open,
! .close = belkin_sa_close,
! .read_int_callback = belkin_sa_read_int_callback, /* How we get the status info */
! .ioctl = belkin_sa_ioctl,
! .set_termios = belkin_sa_set_termios,
! .break_ctl = belkin_sa_break_ctl,
! .startup = belkin_sa_startup,
! .shutdown = belkin_sa_shutdown,
};
--- 103,248 ----
static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
! static __devinitdata struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
{ } /* Terminating entry */
};
+ static __devinitdata struct usb_device_id belkin_dockstation_table [] = {
+ { USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
+ { } /* Terminating entry */
+ };
+
+ static __devinitdata struct usb_device_id belkin_sa_table [] = {
+ { USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
+ { } /* Terminating entry */
+ };
+
+ static __devinitdata struct usb_device_id belkin_old_table [] = {
+ { USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
+ { } /* Terminating entry */
+ };
+
+ static __devinitdata struct usb_device_id peracom_table [] = {
+ { USB_DEVICE(PERACOM_VID, PERACOM_PID) },
+ { } /* Terminating entry */
+ };
+
+ static __devinitdata struct usb_device_id gocom232_table [] = {
+ { USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
+ { } /* Terminating entry */
+ };
+
MODULE_DEVICE_TABLE (usb, id_table_combined);
! /* All of the device info needed for the Belkin dockstation serial converter */
! static struct usb_serial_device_type belkin_dockstation_device = {
! name: "Belkin F5U120-PC USB Serial Adapter",
! id_table: belkin_dockstation_table, /* the Belkin F5U103 device */
! needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
! needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
! needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
! num_interrupt_in: 1,
! num_bulk_in: 1,
! num_bulk_out: 1,
! num_ports: 1,
! open: belkin_sa_open,
! close: belkin_sa_close,
! read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
! ioctl: belkin_sa_ioctl,
! set_termios: belkin_sa_set_termios,
! break_ctl: belkin_sa_break_ctl,
! startup: belkin_sa_startup,
! shutdown: belkin_sa_shutdown,
! };
!
! /* All of the device info needed for the Belkin serial converter */
! static struct usb_serial_device_type belkin_sa_device = {
! name: "Belkin F5U103 USB Serial Adapter",
! id_table: belkin_sa_table, /* the Belkin F5U103 device */
! needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
! needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
! needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
! num_interrupt_in: 1,
! num_bulk_in: 1,
! num_bulk_out: 1,
! num_ports: 1,
! open: belkin_sa_open,
! close: belkin_sa_close,
! read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
! ioctl: belkin_sa_ioctl,
! set_termios: belkin_sa_set_termios,
! break_ctl: belkin_sa_break_ctl,
! startup: belkin_sa_startup,
! shutdown: belkin_sa_shutdown,
! };
!
!
! /* This driver also supports the "old" school Belkin single port adaptor */
! static struct usb_serial_device_type belkin_old_device = {
! name: "Belkin USB Serial Adapter",
! id_table: belkin_old_table, /* the old Belkin device */
! needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
! needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
! needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
! num_interrupt_in: 1,
! num_bulk_in: 1,
! num_bulk_out: 1,
! num_ports: 1,
! open: belkin_sa_open,
! close: belkin_sa_close,
! read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
! ioctl: belkin_sa_ioctl,
! set_termios: belkin_sa_set_termios,
! break_ctl: belkin_sa_break_ctl,
! startup: belkin_sa_startup,
! shutdown: belkin_sa_shutdown,
! };
!
! /* this driver also works for the Peracom single port adapter */
! static struct usb_serial_device_type peracom_device = {
! name: "Peracom single port USB Serial Adapter",
! id_table: peracom_table, /* the Peracom device */
! needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
! needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
! needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
! num_interrupt_in: 1,
! num_bulk_in: 1,
! num_bulk_out: 1,
! num_ports: 1,
! open: belkin_sa_open,
! close: belkin_sa_close,
! read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
! ioctl: belkin_sa_ioctl,
! set_termios: belkin_sa_set_termios,
! break_ctl: belkin_sa_break_ctl,
! startup: belkin_sa_startup,
! shutdown: belkin_sa_shutdown,
! };
!
! /* the GoHubs Go-COM232 device is the same as the Peracom single port adapter */
! static struct usb_serial_device_type gocom232_device = {
! name: "GO-COM232 USB Serial Converter",
! id_table: gocom232_table, /* the GO-COM232 device */
! needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
! needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
! needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
! num_interrupt_in: 1,
! num_bulk_in: 1,
! num_bulk_out: 1,
! num_ports: 1,
! open: belkin_sa_open,
! close: belkin_sa_close,
! read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
! ioctl: belkin_sa_ioctl,
! set_termios: belkin_sa_set_termios,
! break_ctl: belkin_sa_break_ctl,
! startup: belkin_sa_startup,
! shutdown: belkin_sa_shutdown,
};
***************
*** 185,194 ****
{
int i;
! dbg ("%s", __FUNCTION__);
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
if (serial->port[i].private)
kfree(serial->port[i].private);
--- 296,308 ----
{
int i;
! dbg (__FUNCTION__);
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
+ while (serial->port[i].open_count > 0) {
+ belkin_sa_close (&serial->port[i], NULL);
+ }
/* My special items, the standard routines free my urbs */
if (serial->port[i].private)
kfree(serial->port[i].private);
***************
*** 200,224 ****
{
int retval = 0;
! dbg("%s port %d", __FUNCTION__, port->number);
! /*Start reading from the device*/
! /* TODO: Look at possibility of submitting mulitple URBs to device to
! * enhance buffering. Win trace shows 16 initial read URBs.
! */
! port->read_urb->dev = port->serial->dev;
! retval = usb_submit_urb(port->read_urb);
! if (retval) {
! err("usb_submit_urb(read bulk) failed");
! goto exit;
! }
!
! port->interrupt_in_urb->dev = port->serial->dev;
! retval = usb_submit_urb(port->interrupt_in_urb);
! if (retval)
! err(" usb_submit_urb(read int) failed");
exit:
return retval;
} /* belkin_sa_open */
--- 314,349 ----
{
int retval = 0;
! dbg(__FUNCTION__" port %d", port->number);
! down (&port->sem);
!
! ++port->open_count;
! MOD_INC_USE_COUNT;
!
! if (!port->active) {
! port->active = 1;
+ /*Start reading from the device*/
+ /* TODO: Look at possibility of submitting mulitple URBs to device to
+ * enhance buffering. Win trace shows 16 initial read URBs.
+ */
+ port->read_urb->dev = port->serial->dev;
+ retval = usb_submit_urb(port->read_urb);
+ if (retval) {
+ err("usb_submit_urb(read bulk) failed");
+ goto exit;
+ }
+
+ port->interrupt_in_urb->dev = port->serial->dev;
+ retval = usb_submit_urb(port->interrupt_in_urb);
+ if (retval)
+ err(" usb_submit_urb(read int) failed");
+ }
+
exit:
+ up (&port->sem);
+
return retval;
} /* belkin_sa_open */
***************
*** 234,247 ****
if (!serial)
return;
! dbg("%s port %d", __FUNCTION__, port->number);
! if (serial->dev) {
! /* shutdown our bulk reads and writes */
! usb_unlink_urb (port->write_urb);
! usb_unlink_urb (port->read_urb);
! usb_unlink_urb (port->interrupt_in_urb);
}
} /* belkin_sa_close */
--- 359,382 ----
if (!serial)
return;
! dbg(__FUNCTION__" port %d", port->number);
!
! down (&port->sem);
!
! --port->open_count;
! if (port->open_count <= 0) {
! if (serial->dev) {
! /* shutdown our bulk reads and writes */
! usb_unlink_urb (port->write_urb);
! usb_unlink_urb (port->read_urb);
! usb_unlink_urb (port->interrupt_in_urb);
! }
! port->active = 0;
}
+
+ up (&port->sem);
+ MOD_DEC_USE_COUNT;
} /* belkin_sa_close */
***************
*** 322,352 ****
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private;
! unsigned int iflag;
! unsigned int cflag;
! unsigned int old_iflag = 0;
! unsigned int old_cflag = 0;
__u16 urb_value = 0; /* Will hold the new flags */
- if ((!port->tty) || (!port->tty->termios)) {
- dbg ("%s - no tty or termios structure", __FUNCTION__);
- return;
- }
-
- iflag = port->tty->termios->c_iflag;
- cflag = port->tty->termios->c_cflag;
-
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - nothing to change...", __FUNCTION__);
- return;
- }
- old_iflag = old_termios->c_iflag;
- old_cflag = old_termios->c_cflag;
- }
-
/* Set the baud rate */
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
/* reassert DTR and (maybe) RTS on transition from B0 */
--- 457,468 ----
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private;
! unsigned int iflag = port->tty->termios->c_iflag;
! unsigned int cflag = port->tty->termios->c_cflag;
! unsigned int old_iflag = old_termios->c_iflag;
! unsigned int old_cflag = old_termios->c_cflag;
__u16 urb_value = 0; /* Will hold the new flags */
/* Set the baud rate */
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
/* reassert DTR and (maybe) RTS on transition from B0 */
***************
*** 526,532 ****
static int __init belkin_sa_init (void)
{
! usb_serial_register (&belkin_device);
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
--- 642,652 ----
static int __init belkin_sa_init (void)
{
! usb_serial_register (&belkin_dockstation_device);
! usb_serial_register (&belkin_sa_device);
! usb_serial_register (&belkin_old_device);
! usb_serial_register (&peracom_device);
! usb_serial_register (&gocom232_device);
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
***************
*** 534,540 ****
static void __exit belkin_sa_exit (void)
{
! usb_serial_deregister (&belkin_device);
}
--- 654,664 ----
static void __exit belkin_sa_exit (void)
{
! usb_serial_deregister (&belkin_dockstation_device);
! usb_serial_deregister (&belkin_sa_device);
! usb_serial_deregister (&belkin_old_device);
! usb_serial_deregister (&peracom_device);
! usb_serial_deregister (&gocom232_device);
}
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/belkin_sa.h LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/belkin_sa.h
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/belkin_sa.h 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/belkin_sa.h 2004-05-24 17:35:29.000000000 +0900
***************
*** 47,53 ****
#define GOHUBS_VID 0x0921 /* GoHubs vendor id */
#define GOHUBS_PID 0x1000 /* GoHubs single port serial converter's id (identical to the Peracom device) */
- #define HANDYLINK_PID 0x1200 /* HandyLink USB's id (identical to the Peracom device) */
/* Vendor Request Interface */
#define BELKIN_SA_SET_BAUDRATE_REQUEST 0 /* Set baud rate */
--- 47,52 ----
diff -rc HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/cyberjack.c LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/cyberjack.c
*** HGLAN/source_CD/linux-2.4.17_mvl21/drivers/usb/serial/cyberjack.c 2004-04-08 22:41:33.000000000 +0900
--- LAN/source_CD/linux-2.4.17_mvl21-sandpoint/drivers/usb/serial/cyberjack.c 2004-05-24 17:35:29.000000000 +0900
***************
*** 25,39 ****
#include
#include
#include
#include
#include
#include
#include
#include
#include