GadgetSeed  0.9.6
device.c
[詳解]
1 /** @file
2  @brief デバイスドライバAPI
3 
4  GadgetSeed は標準化されたデバイスアクセスのための API を提供します。
5 
6  GadgetSeed のデバイスドライバは struct st_device 構造体で定義されています。
7 
8  @date 2007.03.18
9  @author Takashi SHUDO
10 
11  @page device_driver デバイスドライバ
12 
13  GadgetSeedは標準化されたデバイスドライバAPIとデバイスドライバ構造体が定義されています。
14 
15  これらは device.h で定義されています。
16 
17 
18  ---
19  @section device_driver_struct デバイスドライバ構造体
20 
21  デバイスドライバ構造体は以下の構造体で定義されています。
22 
23  @ref st_device @copybrief st_device
24 
25  GadgetSeedでアプリケーションがIOをアクセスするにはデバイスドライバを経由することを推奨します。\n
26  GadgetSeedでデバイスドライバを開発することは @ref device データとそのメソッドを作成することになります。
27 
28 
29  ---
30  @section device_driver_api デバイスドライバユーザAPI
31 
32  ユーザがデバイスにアクセスするためのAPIとして、以下のAPIがあります。
33 
34  include ファイル : device.h
35 
36  | API名 | 機能 |
37  |:--------------------------|:------------------------------|
38  | open_device() | @copybrief open_device |
39  | close_device() | @copybrief close_device |
40  | lock_device() | @copybrief lock_device |
41  | unlock_device() | @copybrief unlock_device |
42  | read_device() | @copybrief read_device |
43  | block_read_device() | @copybrief block_read_device |
44  | getc_device() | @copybrief getc_device |
45  | write_device() | @copybrief write_device |
46  | block_write_device() | @copybrief block_write_device |
47  | putc_device() | @copybrief putc_device |
48  | ioctl_device() | @copybrief ioctl_device |
49  | seek_device() | @copybrief seek_device |
50  | sync_device() | @copybrief sync_device |
51  | select_device() | @copybrief select_device |
52 
53 
54  ---
55  @section device_type デバイスタイプ
56 
57  GadgetSeedでは以下のデバイスタイプが定義されています。
58  また、各デバイスタイプで実装すべき ioctl コマンドが規定されています。
59  ioctl コマンドは各デバイスタイプ用の include ファイルに定義されています。
60 
61  | デバイスタイプ | 説明 | includeファイル |
62  |:------------------|:--------------------------------------|-----------------------|
63  | タイマ | 汎用タイマデバイス | timer_ioctl.h |
64  | UART | シリアル通信デバイス | uart_ioctl.h |
65  | RTC時計 | リアルタイムクロックデバイス | rtc_ioctl.h |
66  | I2Cマスター | I2Cマスターコントローラデバイス | i2c_ioctl.h |
67  | SPIマスター | SPIマスターコントローラデバイス | spi_ioctl.h |
68  | ストレージ | SD、MMC等のストレージデバイス | sd_ioctl.h |
69  | ビデオ出力 | LCD等の画像表示デバイス | video_ioctl.h |
70  | ビデオIO | 画像表示デバイス制御用IO | vio_ioctl.h |
71  | 圧電ブザー | 圧電ブザー等のサウンダデバイス | buzzer_ioctl.h |
72  | 外部割り込み(IRQ) | 外部割り込み端子 | irq_ioctl.h |
73  | Etherデバイス | Etherデバイス | ether_ioctl.h |
74  | GPIO | GPIOデバイス | gpio_ioctl.h |
75  | AUDIO | AUDIOデバイス | audio_ioctl.h |
76  | タッチセンサ | タッチセンサデバイス | ts_ioctl.h |
77  | 環境センサ | 温度センサ、湿度センサ、気圧センサ等 | envsnsr_ioctl.h |
78 */
79 
80 #include "sysconfig.h"
81 #include "interrupt.h"
82 #include "device.h"
83 #include "task/syscall.h"
84 #include "str.h"
85 #include "tkprintf.h"
86 
87 //#define DEBUGKBITS 0x03
88 #include "dkprintf.h"
89 
90 #ifndef GSC_KERNEL_MAX_DEVICE_NUM
91 #define GSC_KERNEL_MAX_DEVICE_NUM 16 ///< $gsc カーネル最大デバイスドライバ数
92 #endif
93 
94 static struct st_device *device_list[GSC_KERNEL_MAX_DEVICE_NUM]; ///< 登録デバイスリスト
95 
96 /**
97  @brief デバイスドライバリストを初期化する
98 */
99 void init_device_list(void)
100 {
101  short i;
102 
103  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
104  device_list[i] = 0;
105  }
106 }
107 
108 /**
109  @brief 登録されているデバイス数を取得する
110 
111  @return デバイス数
112 */
113 int device_num(void)
114 {
115  int i, num = 0;
116  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
117  if(device_list[i] != 0) {
118  num ++;
119  }
120  }
121 
122  return num;
123 }
124 
125 /**
126  @brief デバイス名を取得する
127 
128  @param[in] num デバイス名
129 
130  @return デバイス名
131 */
132 const char * device_name(int num)
133 {
134  int i, n = 0;
135  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
136  if(device_list[i] != 0) {
137  if(n == num) {
138  return device_list[i]->name;
139  }
140  n ++;
141  }
142  }
143 
144  return (char *)0;
145 }
146 
147 /**
148  @brief デバイス説明を取得する
149 
150  @param[in] num デバイス番号
151 
152  @return デバイス説明
153 */
154 const char * device_explan(int num)
155 {
156  int i, n = 0;
157  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
158  if(device_list[i] != 0) {
159  if(n == num) {
160  return device_list[i]->explan;
161  }
162  n ++;
163  }
164  }
165 
166  return (char *)0;
167 }
168 
169 /**
170  @brief デバイスを登録する
171 
172  @param[in] dev デバイスドライバ
173  @param[in] context デバイスコンテキストデータポインタ(プライベートデータ)
174  @param[in] param ドライバパラメタ
175 
176  @return !=0:エラー
177 */
178 extern int flg_init_task_run;
179 
180 int register_device(const struct st_device *dev, char *param)
181 {
182  short i;
183 
184  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
185  if(device_list[i] == 0) {
186  int rt = 0;
187  if(dev->register_dev) {
188  DKPRINTF(0x01, "Device \"%s\" install ", dev->name);
189  if(dev->mutex != 0) {
190  if(flg_init_task_run == 0) {
191  mutex_register_ISR(dev->mutex, dev->name);
192  } else {
193  mutex_register(dev->mutex, dev->name);
194  }
195  }
196  rt = dev->register_dev((struct st_device *)dev, param);
197  }
198 
199  if(rt == 0) {
200  device_list[i] = (struct st_device *)dev;
201  DKPRINTF(0x01, "OK.\n");
202  return 0;
203  } else {
204  DKPRINTF(0x01, "NG.\n");
205  SYSERR_PRINT("\"%s\" register error.\n",
206  dev->name);
207  return -1;
208  }
209  }
210  }
211 
212  SYSERR_PRINT("Cannot register device \"%s\" (over GSC_KERNEL_MAX_DEVICE_NUM).\n",
213  dev->name);
214 
215  return -1;
216 }
217 
218 /**
219  @brief デバイスを削除する
220 
221  @param[in] dev デバイスドライバ
222 
223  @return !=0:エラー
224 */
225 int unregister_device(const struct st_device *dev)
226 {
227  short i;
228 
229  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
230  if(device_list[i] == dev) {
231  int j;
232  for(j=i; j<(GSC_KERNEL_MAX_DEVICE_NUM - 1); j++) {
233  device_list[j] = device_list[j+1];
234  }
235  device_list[GSC_KERNEL_MAX_DEVICE_NUM - 1] = 0;
236  if(dev->unregister_dev) {
237  int rtn = dev->unregister_dev((struct st_device *)dev);
238  if(dev->mutex != 0) {
239  if(flg_init_task_run == 0) {
240  (void)mutex_unregister_ISR(dev->mutex);
241  } else {
242  mutex_unregister(dev->mutex);
243  }
244  }
245  return rtn;
246  } else {
247  return 0;
248  }
249  }
250  }
251 
252  return -1;
253 }
254 
255 /**
256  @brief デバイスをオープンする
257 
258  @param[in] name デバイス名
259 
260  @return 0:エラー,!=0:デバイスポインタ
261 */
262 struct st_device *open_device(char *name)
263 {
264  short i;
265  int rt;
266 
267  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
268  if(device_list[i] != 0) {
269  if(strcomp((uchar *)name, (uchar *)device_list[i]->name) == 0) {
270  if(device_list[i]->open) {
271  rt = device_list[i]->open(device_list[i]);
272  if(rt != 0) {
273  return 0;
274  }
275  }
276  return device_list[i];
277  }
278  }
279  }
280 
281  return 0;
282 }
283 
284 /**
285  @brief デバイスをクローズする
286 
287  @param[in] dev デバイスドライバ
288 
289  @return !=0:エラー
290 */
291 int close_device(struct st_device *dev)
292 {
293  if(dev != 0) {
294  if(dev->close) {
295  return dev->close(dev);
296  }
297  }
298 
299  return -1;
300 }
301 
302 /**
303  @brief デバイスをロックする
304 
305  @param[in] dev デバイスドライバ
306  @param[in] timeout タイムアウト時間(msec)
307 
308  @return !=0:エラー
309 */
310 int lock_device(struct st_device *dev, unsigned int timeout)
311 {
312  DKPRINTF(0x02, "DEV %s LOCK Timeout %ld\n", dev->name, timeout);
313 
314  if(is_in_interrupt() != 0) {
315  DKPRINTF(0x02, "DEV %s LOCK abort is_in_interrupt\n", dev->name);
316  return 0;
317  }
318 
319  if(flg_init_task_run == 0) {
320  DKPRINTF(0x02, "DEV %s LOCK abort flg_init_task_run\n", dev->name);
321  return 0;
322  }
323 
324  if(dev != 0) {
325  if(dev->mutex != 0) {
326  DKPRINTF(0x02, "DEV %s LOCK\n", dev->name);
327  return mutex_lock(dev->mutex, timeout);
328  } else {
329  return -1;
330  }
331  }
332 
333  return 0;
334 }
335 
336 /**
337  @brief デバイスをアンロックする
338 
339  @param[in] dev デバイスドライバ
340 
341  @return !=0:エラー
342 */
343 int unlock_device(struct st_device *dev)
344 {
345  DKPRINTF(0x02, "DEV %s UNLOCK\n", dev->name);
346 
347  if(is_in_interrupt()) {
348  DKPRINTF(0x02, "DEV %s UNLOCK abort is_in_interrupt\n", dev->name);
349  return 0;
350  }
351 
352  if(flg_init_task_run == 0) {
353  DKPRINTF(0x02, "DEV %s UNLOCK abort flg_init_task_run\n", dev->name);
354  return 0;
355  }
356 
357  if(dev != 0) {
358  if(dev->mutex != 0) {
359  DKPRINTF(0x02, "DEV %s UNLOCK\n", dev->name);
360  return mutex_unlock(dev->mutex);
361  } else {
362  return -1;
363  }
364  }
365 
366  return 0;
367 }
368 
369 /**
370  @brief デバイスよりデータを読み出す
371 
372  @param[in] dev デバイスドライバ
373  @param[out] buf 読み出しデータポインタ
374  @param[in] count 読み出しデータバイト数
375 
376  @return 読み出しデータバイト数,<0:エラー
377 */
378 int read_device(struct st_device *dev, void *buf, unsigned int count)
379 {
380  if(dev != 0) {
381  if(dev->read) {
382  return dev->read(dev, buf, count);
383  } else if(dev->getc) {
384  unsigned int i;
385  unsigned char *dp = buf;
386  for(i=0; i<count; i++) {
387  if(dev->getc(dev, dp)) {
388  dp ++;
389  } else {
390  break;
391  }
392  }
393  return (int)i;
394  }
395  }
396 
397  return -1;
398 }
399 
400 /**
401  @brief デバイスよりブロックデータを読み出す
402 
403  @param[in] dev デバイスドライバ
404  @param[out] buf 読み出しデータポインタ
405  @param[in] sector 読み出しデータセクター
406  @param[in] blkcount 読み出しデータブロック数
407 
408  @return 読み出しデータバイト数,<0:エラー
409 */
410 int block_read_device(struct st_device *dev, void *buf, unsigned int sector, unsigned int blkcount)
411 {
412  if(dev != 0) {
413  if(dev->block_read) {
414  return dev->block_read(dev, buf, sector, blkcount);
415  }
416  }
417 
418  return -1;
419 }
420 
421 /**
422  @brief デバイスよりデータを1バイト読み出す
423 
424  @param[in] dev デバイスドライバ
425  @param[out] data 読み出しデータポインタ
426 
427  @return <0:エラー
428 */
429 int getc_device(struct st_device *dev, unsigned char *data)
430 {
431  if(dev != 0) {
432  if(dev->getc) {
433  return dev->getc(dev, data);
434  } else if(dev->read) {
435  return dev->read(dev, data, 1);
436  }
437  }
438 
439  return -1;
440 }
441 
442 /**
443  @brief デバイスにデータを書き込む
444 
445  @param[in] dev デバイスドライバ
446  @param[in] buf 書き込みデータポインタ
447  @param[in] count 書き込みデータバイト数
448 
449  @return 書き込みデータバイト数,<0:エラー
450 */
451 int write_device(struct st_device *dev, const void *buf, unsigned int count)
452 {
453  if(dev != 0) {
454  if(dev->write) {
455  return dev->write(dev, buf, count);
456  } else if(dev->putc) {
457  unsigned int i;
458  const unsigned char *dp = buf;
459  for(i=0; i<count; i++) {
460  if(dev->putc(dev, *dp)) {
461  dp ++;
462  } else {
463  break;
464  }
465  }
466  return (int)i;
467  }
468  }
469 
470  return -1;
471 }
472 
473 /**
474  @brief デバイスにブロックデータを書き込む
475 
476  @param[in] dev デバイスドライバ
477  @param[in] buf 書き込みデータポインタ
478  @param[in] sector 書き込みデータセクター
479  @param[in] blkcount 書き込みデータブロック数
480 
481  @return 書き込みデータバイト数,<0:エラー
482 */
483 int block_write_device(struct st_device *dev, const void *buf, unsigned int sector, unsigned int blkcount)
484 {
485  if(dev != 0) {
486  if(dev->block_write) {
487  return dev->block_write(dev, buf, sector, blkcount);
488  }
489  }
490 
491  return -1;
492 }
493 
494 /**
495  @brief デバイスにデータを1バイト書き込む
496 
497  @param[in] dev デバイスドライバ
498  @param[out] data 読み出しデータ
499 
500  @return <0:エラー
501 */
502 int putc_device(struct st_device *dev, unsigned char data)
503 {
504  if(dev != 0) {
505  if(dev->putc) {
506  return dev->putc(dev, data);
507  } else if(dev->write) {
508  unsigned char buf = data;
509  return dev->write(dev, &buf, 1);
510  }
511  }
512 
513  return -1;
514 }
515 
516 /**
517  @brief デバイスを制御する
518 
519  @param[in] dev デバイスドライバ
520  @param[in] com コマンド
521  @param[in] arg コマンド引数
522 
523  @return <0:エラー
524 */
525 int ioctl_device(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
526 {
527  if(dev != 0) {
528  if(dev->ioctl) {
529  return dev->ioctl(dev, com, arg, param);
530  }
531  }
532 
533  return -1;
534 }
535 
536 /**
537  @brief デバイスのアクセスポイントを設定する
538 
539  @param[in] dev デバイスドライバ
540  @param[in] offset オフセット
541  @param[in] whence オフセット開始位置
542 
543  @return <0:エラー
544 */
545 int seek_device(struct st_device *dev, int offset, int whence)
546 {
547  if(dev != 0) {
548  if(dev->seek) {
549  return dev->seek(dev, offset, whence);
550  }
551  }
552 
553  return -1;
554 }
555 
556 /**
557  @brief デバイスの書き込みデータの同期をとる
558 
559  @param[in] dev デバイスドライバ
560 
561  @return <0:エラー
562 */
563 int sync_device(struct st_device *dev)
564 {
565  if(dev != 0) {
566  if(dev->sync) {
567  return dev->sync(dev);
568  }
569  }
570 
571  return -1;
572 }
573 
574 /**
575  @brief デバイスのアクセス準備完了を待つ
576 
577  @param[in] dev デバイスドライバ
578  @param[in] timeout タイムアウト時間
579 
580  @return <0:エラー
581 */
582 int select_device(struct st_device *dev, unsigned int timeout)
583 {
584  if(dev != 0) {
585  if(dev->select) {
586  return dev->select(dev, timeout);
587  }
588  }
589 
590  return -1;
591 }
592 
593 /**
594  @brief デバイスを休止状態にする
595 
596  @param[in] dev デバイスドライバ
597 
598  @return <0:エラー
599 */
600 int suspend_device(struct st_device *dev)
601 {
602  if(dev != 0) {
603  if(dev->suspend) {
604  return dev->suspend(dev);
605  }
606  }
607 
608  return -1;
609 }
610 
611 /**
612  @brief デバイスを活性化する
613 
614  @param[in] dev デバイスドライバ
615 
616  @return <0:エラー
617 */
618 int resume_device(struct st_device *dev)
619 {
620  if(dev != 0) {
621  if(dev->resume) {
622  return dev->resume(dev);
623  }
624  }
625 
626  return -1;
627 }
628 
629 /**
630  @brief 全デバイスを休止状態にする
631 
632  @return <0:エラー
633 */
634 int suspend(void)
635 {
636  int i;
637 
638  for(i=(GSC_KERNEL_MAX_DEVICE_NUM-1); i>=0; i--) {
639  if(device_list[i]) {
640  DKPRINTF(0x01, "suspend : %s\n", device_list[i]->name);
641  (void)suspend_device(device_list[i]);
642  }
643  }
644 
645  return 0;
646 }
647 
648 #include "datetime.h"
649 
650 /**
651  @brief 全デバイスを活性化する
652 
653  @return <0:エラー
654 */
655 int resume(void)
656 {
657  int i;
658 
659  for(i=0; i<GSC_KERNEL_MAX_DEVICE_NUM; i++) {
660  if(device_list[i]) {
661  DKPRINTF(0x01, "resume : %s\n", device_list[i]->name);
662  (void)resume_device(device_list[i]);
663  }
664  }
665 
666 #ifdef GSC_DEV_ENABLE_RTC
667  sync_systime_from_rtc();
668 #endif
669 
670  return 0;
671 }
unsigned char uchar
GadgetSeedの文字(列)は unsigned char 型となる
Definition: str.h:13
int read_device(struct st_device *dev, void *buf, unsigned int count)
デバイスよりデータを読み出す
Definition: device.c:378
int lock_device(struct st_device *dev, unsigned int timeout)
デバイスをロックする
Definition: device.c:310
int unregister_device(const struct st_device *dev)
デバイスを削除する
Definition: device.c:225
int close_device(struct st_device *dev)
デバイスをクローズする
Definition: device.c:291
void init_device_list(void)
デバイスドライバリストを初期化する
Definition: device.c:99
void mutex_register(struct st_mutex *mutex, const char *name)
MUTEXを登録する
Definition: syscall_api.c:497
int block_read_device(struct st_device *dev, void *buf, unsigned int sector, unsigned int blkcount)
デバイスよりブロックデータを読み出す
Definition: device.c:410
struct st_mutex * mutex
デバイス排他アクセス用MUTEX
Definition: device.h:30
int resume_device(struct st_device *dev)
デバイスを活性化する
Definition: device.c:618
文字列処理
const char * device_explan(int num)
デバイス説明を取得する
Definition: device.c:154
int ioctl_device(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
デバイスを制御する
Definition: device.c:525
int mutex_lock(struct st_mutex *mutex, unsigned int timeout)
MUTEXをロックする
Definition: syscall_api.c:517
int write_device(struct st_device *dev, const void *buf, unsigned int count)
デバイスにデータを書き込む
Definition: device.c:451
int block_write_device(struct st_device *dev, const void *buf, unsigned int sector, unsigned int blkcount)
デバイスにブロックデータを書き込む
Definition: device.c:483
日付時刻
#define GSC_KERNEL_MAX_DEVICE_NUM
$gsc カーネル最大デバイスドライバ数
Definition: device.c:91
int mutex_unlock(struct st_mutex *mutex)
MUTEXをアンロックする
Definition: syscall_api.c:543
カーネル用機能限定printf
int suspend(void)
全デバイスを休止状態にする
Definition: device.c:634
int unlock_device(struct st_device *dev)
デバイスをアンロックする
Definition: device.c:343
const char * device_name(int num)
デバイス名を取得する
Definition: device.c:132
int strcomp(const uchar *s1, const uchar *s2)
文字列比較
Definition: str.c:583
int sync_device(struct st_device *dev)
デバイスの書き込みデータの同期をとる
Definition: device.c:563
char explan[32]
デバイス説明文字列
Definition: device.h:27
struct st_device * open_device(char *name)
デバイスをオープンする
Definition: device.c:262
システムコール
int putc_device(struct st_device *dev, unsigned char data)
デバイスにデータを1バイト書き込む
Definition: device.c:502
割り込みハンドラ
int flg_init_task_run
デバイスを登録する
Definition: init.c:81
int select_device(struct st_device *dev, unsigned int timeout)
デバイスのアクセス準備完了を待つ
Definition: device.c:582
int suspend_device(struct st_device *dev)
デバイスを休止状態にする
Definition: device.c:600
int resume(void)
全デバイスを活性化する
Definition: device.c:655
デバイスドライバAPI
int device_num(void)
登録されているデバイス数を取得する
Definition: device.c:113
デバイスドライバ構造体
Definition: device.h:25
int seek_device(struct st_device *dev, int offset, int whence)
デバイスのアクセスポイントを設定する
Definition: device.c:545
int getc_device(struct st_device *dev, unsigned char *data)
デバイスよりデータを1バイト読み出す
Definition: device.c:429
カーネル、ドライバ(非タスク)デバッグ用マクロ
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
void mutex_register_ISR(struct st_mutex *mutex, const char *name)
MUTEXを登録する
Definition: mutex.c:37
int mutex_unregister_ISR(struct st_mutex *mutex)
MUTEXを登録解除する
Definition: mutex.c:56
void mutex_unregister(struct st_mutex *mutex)
MUTEXを登録解除する
Definition: syscall_api.c:564