1141cc406Sopenharmony_ci/* @file plustek-pp_procfs.c 2141cc406Sopenharmony_ci * @brief this is the interface to the proc filesystem 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de> 5141cc406Sopenharmony_ci * 6141cc406Sopenharmony_ci * History: 7141cc406Sopenharmony_ci * - 0.37 - initial version 8141cc406Sopenharmony_ci * - 0.38 - changes according to generic structure changes 9141cc406Sopenharmony_ci * - 0.39 - added info about forceMode and slowIO 10141cc406Sopenharmony_ci * - 0.40 - no changes 11141cc406Sopenharmony_ci * - 0.41 - no changes 12141cc406Sopenharmony_ci * - 0.42 - changed include names 13141cc406Sopenharmony_ci * - 0.43 - replace _PTDRV_VERx by _PTDRV_VERSTR 14141cc406Sopenharmony_ci * - cleanup 15141cc406Sopenharmony_ci * - 0.44 - PROC_FS changes for newer kernel 16141cc406Sopenharmony_ci * - fix format string issues, as Long types default to int32_t 17141cc406Sopenharmony_ci * now 18141cc406Sopenharmony_ci * . 19141cc406Sopenharmony_ci * <hr> 20141cc406Sopenharmony_ci * This file is part of the SANE package. 21141cc406Sopenharmony_ci * 22141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 23141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 24141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the 25141cc406Sopenharmony_ci * License, or (at your option) any later version. 26141cc406Sopenharmony_ci * 27141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 28141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 29141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30141cc406Sopenharmony_ci * General Public License for more details. 31141cc406Sopenharmony_ci * 32141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License 33141cc406Sopenharmony_ci * along with this program. If not, see <https://www.gnu.org/licenses/>. 34141cc406Sopenharmony_ci * 35141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for 36141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE. 37141cc406Sopenharmony_ci * 38141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files 39141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the 40141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public 41141cc406Sopenharmony_ci * License. Your use of that executable is in no way restricted on 42141cc406Sopenharmony_ci * account of linking the SANE library code into it. 43141cc406Sopenharmony_ci * 44141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why 45141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public 46141cc406Sopenharmony_ci * License. 47141cc406Sopenharmony_ci * 48141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in 49141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that 50141cc406Sopenharmony_ci * those changes may be distributed with this exception intact. 51141cc406Sopenharmony_ci * 52141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice 53141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications. 54141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice. 55141cc406Sopenharmony_ci * <hr> 56141cc406Sopenharmony_ci */ 57141cc406Sopenharmony_ci#ifdef __KERNEL__ 58141cc406Sopenharmony_ci#include <linux/proc_fs.h> 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#include "plustek-pp_scan.h" 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci/* toggled by your kernel configuration */ 63141cc406Sopenharmony_ci#ifdef CONFIG_PROC_FS 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci/****************************** static vars **********************************/ 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci/** for the proc filesystem 68141cc406Sopenharmony_ci */ 69141cc406Sopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 70141cc406Sopenharmony_ciextern struct proc_dir_entry proc_root; 71141cc406Sopenharmony_ci#endif 72141cc406Sopenharmony_cistatic struct proc_dir_entry *base = NULL; 73141cc406Sopenharmony_cistatic struct proc_dir_entry *binfo = NULL; 74141cc406Sopenharmony_cistatic ULong devcount; 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci/** parallel port modes... */ 77141cc406Sopenharmony_cistatic char *procfsPortModes[] = { 78141cc406Sopenharmony_ci "EPP", 79141cc406Sopenharmony_ci "SPP", 80141cc406Sopenharmony_ci "BiDi (PS/2)", 81141cc406Sopenharmony_ci "ECP" 82141cc406Sopenharmony_ci "unknown", 83141cc406Sopenharmony_ci NULL 84141cc406Sopenharmony_ci}; 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci/** CCD-Types (as for ASIC 98001 based series) */ 87141cc406Sopenharmony_cistatic TabDef procfsCCDTypes98001[] = { 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci { _CCD_3797, "3797" }, 90141cc406Sopenharmony_ci { _CCD_3717, "3717" }, 91141cc406Sopenharmony_ci { _CCD_535, "535" }, 92141cc406Sopenharmony_ci { _CCD_2556, "2556" }, 93141cc406Sopenharmony_ci { _CCD_518, "518" }, 94141cc406Sopenharmony_ci { _CCD_539, "539" }, 95141cc406Sopenharmony_ci { -1 , "unknown" } 96141cc406Sopenharmony_ci}; 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_ci/** CCD-Types (as for ASIC 98003 based series) */ 99141cc406Sopenharmony_cistatic TabDef procfsCCDTypes98003[] = { 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci { _CCD_3797, "3797" }, 102141cc406Sopenharmony_ci { _CCD_3799, "3799" }, 103141cc406Sopenharmony_ci { _CCD_535, "535" }, 104141cc406Sopenharmony_ci { _CCD_2556, "2556" }, 105141cc406Sopenharmony_ci { _CCD_518, "518" }, 106141cc406Sopenharmony_ci { _CCD_539, "539" }, 107141cc406Sopenharmony_ci { _CCD_3777, "3777" }, 108141cc406Sopenharmony_ci { _CCD_548 , "548" }, 109141cc406Sopenharmony_ci { -1 , "unknown" } 110141cc406Sopenharmony_ci}; 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci/****************************** local functions ******************************/ 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci#ifndef LINUX_24 115141cc406Sopenharmony_ci/** This is called as the fill_inode function when an inode 116141cc406Sopenharmony_ci * is going into (fill = 1) or out of service (fill = 0). 117141cc406Sopenharmony_ci * 118141cc406Sopenharmony_ci * Note: only the top-level directory needs to do this; if 119141cc406Sopenharmony_ci * a lower level is referenced, the parent will be as well. 120141cc406Sopenharmony_ci * 121141cc406Sopenharmony_ci * Here simply a dummy function 122141cc406Sopenharmony_ci */ 123141cc406Sopenharmony_cistatic void procfsFillFunc( struct inode *inode, int fill ) 124141cc406Sopenharmony_ci{ 125141cc406Sopenharmony_ci} 126141cc406Sopenharmony_ci#endif 127141cc406Sopenharmony_ci 128141cc406Sopenharmony_ci/** returns a pointer to the port-mode string 129141cc406Sopenharmony_ci */ 130141cc406Sopenharmony_cistatic const char* procfsGetMode( int mode ) 131141cc406Sopenharmony_ci{ 132141cc406Sopenharmony_ci if((mode < _PORT_EPP) || (mode > _PORT_ECP)) 133141cc406Sopenharmony_ci return procfsPortModes[_PORT_ECP+1]; 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci return procfsPortModes[mode]; 136141cc406Sopenharmony_ci} 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci/** determines CCD-Type string 139141cc406Sopenharmony_ci */ 140141cc406Sopenharmony_cistatic const char* procfsGetCCDType( pScanData ps ) 141141cc406Sopenharmony_ci{ 142141cc406Sopenharmony_ci int i; 143141cc406Sopenharmony_ci int ccd_id = ps->Device.bCCDID; 144141cc406Sopenharmony_ci pTabDef tab = procfsCCDTypes98001; 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci if( _IS_ASIC98(ps->sCaps.AsicID)) { 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_ci if(_ASIC_IS_98003 == ps->sCaps.AsicID) 149141cc406Sopenharmony_ci tab = procfsCCDTypes98003; 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_ci /* seek down the description table */ 152141cc406Sopenharmony_ci for( i = 0; -1 != tab[i].id; i++ ) { 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci if( tab[i].id == ccd_id ) 155141cc406Sopenharmony_ci return tab[i].desc; 156141cc406Sopenharmony_ci } 157141cc406Sopenharmony_ci } else { 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci /* for older scanners only this info is available */ 160141cc406Sopenharmony_ci if( ps->fSonyCCD ) 161141cc406Sopenharmony_ci return "SONY Type"; 162141cc406Sopenharmony_ci else 163141cc406Sopenharmony_ci return "NEC/TOSHIBA Type"; 164141cc406Sopenharmony_ci } 165141cc406Sopenharmony_ci 166141cc406Sopenharmony_ci /* return the last entry if nothing applies! */ 167141cc406Sopenharmony_ci return tab[(sizeof(procfsCCDTypes98001)/sizeof(TabDef)-1)].desc; 168141cc406Sopenharmony_ci} 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_ci/** will be called when reading the proc filesystem: 171141cc406Sopenharmony_ci * cat /proc/pt_drv/info 172141cc406Sopenharmony_ci */ 173141cc406Sopenharmony_cistatic int procfsBInfoReadProc( char *buf, char **start, off_t offset, 174141cc406Sopenharmony_ci int count, int *eof, void *data ) 175141cc406Sopenharmony_ci{ 176141cc406Sopenharmony_ci int len = 0; 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci len += sprintf( buf, "Plustek Flatbed Scanner Driver version "_PTDRV_VERSTR"\n" ); 179141cc406Sopenharmony_ci len += sprintf( buf + len, "IOCTL-Version: 0x%08x\n",_PTDRV_IOCTL_VERSION); 180141cc406Sopenharmony_ci return len; 181141cc406Sopenharmony_ci} 182141cc406Sopenharmony_ci 183141cc406Sopenharmony_ci/** will be called when reading the proc filesystem: 184141cc406Sopenharmony_ci * cat /proc/pt_drv/deviceX/info 185141cc406Sopenharmony_ci */ 186141cc406Sopenharmony_cistatic int procfsInfoReadProc( char *buf, char **start, off_t offset, 187141cc406Sopenharmony_ci int count, int *eof, void *data ) 188141cc406Sopenharmony_ci{ 189141cc406Sopenharmony_ci int len = 0; 190141cc406Sopenharmony_ci pScanData ps = (pScanData)data; 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci /* Tell us something about the device... */ 193141cc406Sopenharmony_ci if( NULL != ps ) { 194141cc406Sopenharmony_ci len += sprintf( buf+len, "Model : %s\n", 195141cc406Sopenharmony_ci MiscGetModelName(ps->sCaps.Model)); 196141cc406Sopenharmony_ci len += sprintf( buf+len, "Portaddress : 0x%X\n", ps->IO.portBase ); 197141cc406Sopenharmony_ci len += sprintf( buf+len, "Portmode : %s (%s I/O, %s)\n", 198141cc406Sopenharmony_ci procfsGetMode(ps->IO.portMode), 199141cc406Sopenharmony_ci (ps->IO.slowIO == _TRUE?"delayed":"fast"), 200141cc406Sopenharmony_ci (ps->IO.forceMode == 0?"autodetect":"forced")); 201141cc406Sopenharmony_ci len += sprintf( buf+len, "Buttons : %u\n", ps->Device.buttons); 202141cc406Sopenharmony_ci len += sprintf( buf+len, "Warmuptime : %us\n", ps->warmup ); 203141cc406Sopenharmony_ci len += sprintf( buf+len, "Lamp timeout: %us\n", ps->lampoff ); 204141cc406Sopenharmony_ci len += sprintf( buf+len, "mov-switch : %u\n", ps->ModelOverride ); 205141cc406Sopenharmony_ci len += sprintf( buf+len, "I/O-delay : %u\n", ps->IO.delay ); 206141cc406Sopenharmony_ci len += sprintf( buf+len, "CCD-Type : %s\n", procfsGetCCDType(ps)); 207141cc406Sopenharmony_ci len += sprintf( buf+len, "TPA : %s\n", 208141cc406Sopenharmony_ci (ps->sCaps.dwFlag & SFLAG_TPA) ? "yes":"no" ); 209141cc406Sopenharmony_ci } 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci return len; 212141cc406Sopenharmony_ci} 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci/** will be called when reading the proc filesystem: 215141cc406Sopenharmony_ci * cat /proc/pt_drv/devicex/buttony 216141cc406Sopenharmony_ci */ 217141cc406Sopenharmony_cistatic int procfsButtonsReadProc( char *buf, char **start, off_t offset, 218141cc406Sopenharmony_ci int count, int *eof, void *data ) 219141cc406Sopenharmony_ci{ 220141cc406Sopenharmony_ci Byte b; 221141cc406Sopenharmony_ci int bc = 0; 222141cc406Sopenharmony_ci int len = 0; 223141cc406Sopenharmony_ci pScanData ps = (pScanData)data; 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci if( NULL != ps ) { 226141cc406Sopenharmony_ci bc = ps->Device.buttons; 227141cc406Sopenharmony_ci } 228141cc406Sopenharmony_ci 229141cc406Sopenharmony_ci /* Check the buttons... */ 230141cc406Sopenharmony_ci if( 0 != bc ) { 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) { 233141cc406Sopenharmony_ci MiscClaimPort( ps ); 234141cc406Sopenharmony_ci b = IODataRegisterFromScanner( ps, ps->RegStatus ); 235141cc406Sopenharmony_ci if(_FLAG_P96_KEY == (b & _FLAG_P96_KEY)) 236141cc406Sopenharmony_ci b = 0; 237141cc406Sopenharmony_ci else 238141cc406Sopenharmony_ci b = 1; 239141cc406Sopenharmony_ci MiscReleasePort( ps ); 240141cc406Sopenharmony_ci len += sprintf( buf + len, "%u\n", b ); 241141cc406Sopenharmony_ci } else 242141cc406Sopenharmony_ci bc = 0; 243141cc406Sopenharmony_ci } 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci if( 0 == bc ) 246141cc406Sopenharmony_ci len += sprintf( buf + len, "none\n" ); 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci return len; 249141cc406Sopenharmony_ci} 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci/** create a procfs entry 252141cc406Sopenharmony_ci */ 253141cc406Sopenharmony_cistatic struct proc_dir_entry *new_entry( const char *name, mode_t mode, 254141cc406Sopenharmony_ci struct proc_dir_entry *parent ) 255141cc406Sopenharmony_ci{ 256141cc406Sopenharmony_ci#ifndef LINUX_24 257141cc406Sopenharmony_ci int len; 258141cc406Sopenharmony_ci#endif 259141cc406Sopenharmony_ci struct proc_dir_entry *ent; 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci if (mode == S_IFDIR) 262141cc406Sopenharmony_ci mode |= S_IRUGO | S_IXUGO; 263141cc406Sopenharmony_ci else if (mode == 0) 264141cc406Sopenharmony_ci mode = S_IFREG | S_IRUGO; 265141cc406Sopenharmony_ci 266141cc406Sopenharmony_ci#ifndef LINUX_24 267141cc406Sopenharmony_ci len = strlen(name) + 1; 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci /* allocate memory for the entry and the name */ 270141cc406Sopenharmony_ci ent = kmalloc(sizeof(struct proc_dir_entry) + len, GFP_KERNEL); 271141cc406Sopenharmony_ci if( NULL == ent ) 272141cc406Sopenharmony_ci return NULL; 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci memset(ent, 0, sizeof(struct proc_dir_entry)); 275141cc406Sopenharmony_ci 276141cc406Sopenharmony_ci /* position pointer of name to end of the structure*/ 277141cc406Sopenharmony_ci ent->name = ((char *) ent) + sizeof(*ent); 278141cc406Sopenharmony_ci strcpy((char *)ent->name, name ); 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci ent->namelen = strlen(name); 281141cc406Sopenharmony_ci ent->mode = mode; 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_ci if (S_ISDIR(mode)) { 284141cc406Sopenharmony_ci ent->nlink = 2; 285141cc406Sopenharmony_ci ent->fill_inode = &procfsFillFunc; 286141cc406Sopenharmony_ci } else { 287141cc406Sopenharmony_ci ent->nlink = 1; 288141cc406Sopenharmony_ci } 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci proc_register( parent, ent ); 291141cc406Sopenharmony_ci#else 292141cc406Sopenharmony_ci if (mode == S_IFDIR) 293141cc406Sopenharmony_ci ent = proc_mkdir( name, parent ); 294141cc406Sopenharmony_ci else 295141cc406Sopenharmony_ci ent = create_proc_entry( name, mode, parent ); 296141cc406Sopenharmony_ci#endif 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci return ent; 299141cc406Sopenharmony_ci} 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci/** shutdown one proc fs entry 302141cc406Sopenharmony_ci */ 303141cc406Sopenharmony_cistatic inline void destroy_proc_entry( struct proc_dir_entry *root, 304141cc406Sopenharmony_ci struct proc_dir_entry **d ) 305141cc406Sopenharmony_ci{ 306141cc406Sopenharmony_ci#ifndef LINUX_24 307141cc406Sopenharmony_ci proc_unregister( root, (*d)->low_ino ); 308141cc406Sopenharmony_ci kfree(*d); 309141cc406Sopenharmony_ci#else 310141cc406Sopenharmony_ci DBG(DBG_HIGH, "pt_drv: proc del '%s' root='%s'\n", (*d)->name, root->name); 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci remove_proc_entry((*d)->name, root ); 313141cc406Sopenharmony_ci#endif 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci *d = NULL; 316141cc406Sopenharmony_ci} 317141cc406Sopenharmony_ci 318141cc406Sopenharmony_ci/** shutdown the proc-tree for one device 319141cc406Sopenharmony_ci */ 320141cc406Sopenharmony_cistatic void destroy_proc_tree( pScanData ps ) 321141cc406Sopenharmony_ci{ 322141cc406Sopenharmony_ci int i; 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci DBG( DBG_HIGH, "pt_drv: destroy_proc_tree !\n" ); 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci if( ps ) { 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci if( ps->procDir.entry ) { 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci if( ps->procDir.info ) 331141cc406Sopenharmony_ci destroy_proc_entry( ps->procDir.entry, &ps->procDir.info ); 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci for( i = 0; i < ps->Device.buttons; i++ ) { 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ci if( ps->procDir.buttons[i] ) 336141cc406Sopenharmony_ci destroy_proc_entry(ps->procDir.entry, &ps->procDir.buttons[i]); 337141cc406Sopenharmony_ci } 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci destroy_proc_entry( base, &ps->procDir.entry ); 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci} 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci/*************************** exported functions ******************************/ 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci/** initialize our proc-fs stuff 347141cc406Sopenharmony_ci */ 348141cc406Sopenharmony_ciint ProcFsInitialize( void ) 349141cc406Sopenharmony_ci{ 350141cc406Sopenharmony_ci DBG( DBG_HIGH, "ProcFsInitialize()\n" ); 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 353141cc406Sopenharmony_ci base = new_entry( _DRV_NAME, S_IFDIR, &proc_root ); 354141cc406Sopenharmony_ci#else 355141cc406Sopenharmony_ci base = new_entry( _DRV_NAME, S_IFDIR, NULL ); 356141cc406Sopenharmony_ci#endif 357141cc406Sopenharmony_ci 358141cc406Sopenharmony_ci if( NULL != base ) { 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci devcount = 0; 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci binfo = new_entry( "info", 0, base ); 363141cc406Sopenharmony_ci if( NULL != binfo ) { 364141cc406Sopenharmony_ci binfo->read_proc = procfsBInfoReadProc; 365141cc406Sopenharmony_ci binfo->data = &devcount; 366141cc406Sopenharmony_ci } 367141cc406Sopenharmony_ci } 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci return _OK; 370141cc406Sopenharmony_ci} 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci/** cleanup the base entry 373141cc406Sopenharmony_ci */ 374141cc406Sopenharmony_civoid ProcFsShutdown( void ) 375141cc406Sopenharmony_ci{ 376141cc406Sopenharmony_ci DBG( DBG_HIGH, "ProcFsShutdown()\n" ); 377141cc406Sopenharmony_ci 378141cc406Sopenharmony_ci if( NULL != base ) { 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci if( NULL != binfo ) 381141cc406Sopenharmony_ci destroy_proc_entry( base, &binfo ); 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 384141cc406Sopenharmony_ci destroy_proc_entry( &proc_root, &base ); 385141cc406Sopenharmony_ci#else 386141cc406Sopenharmony_ci destroy_proc_entry( NULL, &base ); 387141cc406Sopenharmony_ci#endif 388141cc406Sopenharmony_ci } 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci devcount = 0; 391141cc406Sopenharmony_ci} 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci/** will be called for each device, that has been found 394141cc406Sopenharmony_ci */ 395141cc406Sopenharmony_civoid ProcFsRegisterDevice( pScanData ps ) 396141cc406Sopenharmony_ci{ 397141cc406Sopenharmony_ci int i; 398141cc406Sopenharmony_ci char str[20]; 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci if( NULL == base ) { 401141cc406Sopenharmony_ci printk( KERN_ERR "pt_drv : proc not initialised yet!\n"); 402141cc406Sopenharmony_ci return; 403141cc406Sopenharmony_ci } 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci memset( &ps->procDir, 0, sizeof(ProcDirDef)); 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci sprintf( str, "device%u", ps->devno ); 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci ps->procDir.entry = new_entry( str, S_IFDIR, base ); 410141cc406Sopenharmony_ci if( NULL == ps->procDir.entry ) 411141cc406Sopenharmony_ci goto error_exit; 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci ps->procDir.info = new_entry( "info", 0, ps->procDir.entry ); 414141cc406Sopenharmony_ci if( NULL == ps->procDir.info ) 415141cc406Sopenharmony_ci goto error_exit; 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci ps->procDir.info->read_proc = procfsInfoReadProc; 418141cc406Sopenharmony_ci ps->procDir.info->data = ps; 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci for( i = 0; i < ps->Device.buttons; i++ ) { 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ci sprintf( str, "button%u", i ); 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ci ps->procDir.buttons[i] = new_entry( str, 0, ps->procDir.entry ); 425141cc406Sopenharmony_ci if( NULL == ps->procDir.buttons[i] ) 426141cc406Sopenharmony_ci goto error_exit; 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci ps->procDir.buttons[i]->read_proc = procfsButtonsReadProc; 429141cc406Sopenharmony_ci ps->procDir.buttons[i]->data = ps; 430141cc406Sopenharmony_ci } 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci devcount++; 433141cc406Sopenharmony_ci return; 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_cierror_exit: 437141cc406Sopenharmony_ci 438141cc406Sopenharmony_ci printk(KERN_ERR "pt_drv: failure registering /proc/ entry %s.\n", str ); 439141cc406Sopenharmony_ci destroy_proc_tree( ps ); 440141cc406Sopenharmony_ci} 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ci/** cleanup the proc-fs for a certain device 443141cc406Sopenharmony_ci */ 444141cc406Sopenharmony_civoid ProcFsUnregisterDevice( pScanData ps ) 445141cc406Sopenharmony_ci{ 446141cc406Sopenharmony_ci destroy_proc_tree( ps ); 447141cc406Sopenharmony_ci} 448141cc406Sopenharmony_ci 449141cc406Sopenharmony_ci#else /* CONFIG_PROC_FS */ 450141cc406Sopenharmony_ci 451141cc406Sopenharmony_ciint ProcFsInitialize( void ) 452141cc406Sopenharmony_ci{ 453141cc406Sopenharmony_ci return _OK; 454141cc406Sopenharmony_ci} 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_civoid ProcFsShutdown( void ) 457141cc406Sopenharmony_ci{ 458141cc406Sopenharmony_ci} 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_civoid ProcFsRegisterDevice( pScanData ps ) 461141cc406Sopenharmony_ci{ 462141cc406Sopenharmony_ci} 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_civoid ProcFsUnregisterDevice( pScanData ps ) 465141cc406Sopenharmony_ci{ 466141cc406Sopenharmony_ci} 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci#endif 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci#endif /* guard __KERNEL__ */ 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci/* END PLUSTEK-PP_PROCFS.C ..................................................*/ 473