SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /drivers/tty.c (Article 9) and /drivers/tty.c (Article 9.5)


001 /* Copyright (C) 2005  Thomas Petazzoni, David    001 /* Copyright (C) 2005  Thomas Petazzoni, David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007 
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012 
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA.
017 */                                                017 */
018                                                   018 
019 #include <sos/types.h>                            019 #include <sos/types.h>
020 #include <sos/assert.h>                           020 #include <sos/assert.h>
021 #include <sos/errno.h>                            021 #include <sos/errno.h>
022 #include <sos/fs.h>                               022 #include <sos/fs.h>
023 #include <sos/ksynch.h>                           023 #include <sos/ksynch.h>
024 #include <sos/kwaitq.h>                           024 #include <sos/kwaitq.h>
025 #include <sos/uaccess.h>                          025 #include <sos/uaccess.h>
026 #include <sos/kmalloc.h>                          026 #include <sos/kmalloc.h>
027 #include <sos/list.h>                             027 #include <sos/list.h>
028 #include <sos/chardev.h>                          028 #include <sos/chardev.h>
029 #include <drivers/devices.h>                      029 #include <drivers/devices.h>
030                                                   030 
031 #include "tty.h"                                  031 #include "tty.h"
032                                                   032 
033 #define TTY_BUFFER_LEN 64                         033 #define TTY_BUFFER_LEN 64
034 #define TTY_NAME_LEN   16                         034 #define TTY_NAME_LEN   16
035                                                   035 
036 struct tty_device {                               036 struct tty_device {
037   sos_ui32_t        instance;                     037   sos_ui32_t        instance;
038   unsigned int      open_count;                   038   unsigned int      open_count;
039   char              buffer[TTY_BUFFER_LEN];       039   char              buffer[TTY_BUFFER_LEN];
040   unsigned int      buffer_read;                  040   unsigned int      buffer_read;
041   unsigned int      buffer_write;                 041   unsigned int      buffer_write;
042   struct sos_ksema  sem;                          042   struct sos_ksema  sem;
043   struct sos_kwaitq wq;                           043   struct sos_kwaitq wq;
044   sos_ret_t         (*write)(char c);             044   sos_ret_t         (*write)(char c);
045   unsigned int      param;                        045   unsigned int      param;
046   struct tty_device *next, *prev;                 046   struct tty_device *next, *prev;
047 };                                                047 };
048                                                   048 
049 static struct tty_device *tty_device_list;        049 static struct tty_device *tty_device_list;
050                                                   050 
051 static struct tty_device *                        051 static struct tty_device *
052 tty_device_find (sos_ui32_t instance)             052 tty_device_find (sos_ui32_t instance)
053 {                                                 053 {
054   struct tty_device *t;                           054   struct tty_device *t;
055   int n;                                          055   int n;
056                                                   056 
057   list_foreach (tty_device_list, t, n)            057   list_foreach (tty_device_list, t, n)
058     {                                             058     {
059       if (t->instance == instance)                059       if (t->instance == instance)
060         return t;                                 060         return t;
061     }                                             061     }
062                                                   062 
063   return NULL;                                    063   return NULL;
064 }                                                 064 }
065                                                   065 
066 static sos_ret_t tty_read(struct sos_fs_opened    066 static sos_ret_t tty_read(struct sos_fs_opened_file *this,
067                           sos_uaddr_t dest_buf    067                           sos_uaddr_t dest_buf, sos_size_t *len)
068 {                                                 068 {
069   sos_size_t count = 0;                           069   sos_size_t count = 0;
070   struct tty_device *t;                           070   struct tty_device *t;
071   sos_ret_t ret;                                  071   sos_ret_t ret;
072                                                   072 
073   t = (struct tty_device *) this->custom_data;    073   t = (struct tty_device *) this->custom_data;
074                                                   074 
075   if (*len == 0)                                  075   if (*len == 0)
076     return SOS_OK;                                076     return SOS_OK;
077                                                   077 
078   while (1)                                       078   while (1)
079     {                                             079     {
080       char c;                                     080       char c;
081                                                   081 
082       /* Take the semaphore */                    082       /* Take the semaphore */
083       sos_ksema_down (& t->sem, NULL);            083       sos_ksema_down (& t->sem, NULL);
084                                                   084 
085       /* No keys available in the ring buffer,    085       /* No keys available in the ring buffer, wait until the
086          add_chars callback wakes us up */        086          add_chars callback wakes us up */
087       if (t->buffer_read == t->buffer_write)      087       if (t->buffer_read == t->buffer_write)
088         {                                         088         {
089           sos_ksema_up (& t->sem);                089           sos_ksema_up (& t->sem);
090           sos_kwaitq_wait (& t->wq, NULL);        090           sos_kwaitq_wait (& t->wq, NULL);
091                                                   091 
092           /* Go back to begining of loop: mayb    092           /* Go back to begining of loop: maybe someone else stole the
093              semaphore */                         093              semaphore */
094           continue;                               094           continue;
095         }                                         095         }
096                                                   096 
097       c = t->buffer[t->buffer_read];              097       c = t->buffer[t->buffer_read];
098                                                   098 
099       /* Copy the received character from the     099       /* Copy the received character from the ring buffer to the
100          destination buffer */                    100          destination buffer */
101       ret = sos_memcpy_to_user (dest_buf,         101       ret = sos_memcpy_to_user (dest_buf,
102                                 (sos_vaddr_t)     102                                 (sos_vaddr_t) & t->buffer[t->buffer_read],
103                                 sizeof (char))    103                                 sizeof (char));
104       if (sizeof(char) != ret)                    104       if (sizeof(char) != ret)
105         {                                         105         {
106           *len = count;                           106           *len = count;
107           sos_ksema_up (& t->sem);                107           sos_ksema_up (& t->sem);
108           return ret;                             108           return ret;
109         }                                         109         }
110                                                   110 
111       dest_buf++;                                 111       dest_buf++;
112                                                   112 
113       /* Update the ring buffer read pointer *    113       /* Update the ring buffer read pointer */
114       t->buffer_read++;                           114       t->buffer_read++;
115       if (t->buffer_read == TTY_BUFFER_LEN)       115       if (t->buffer_read == TTY_BUFFER_LEN)
116         t->buffer_read = 0;                       116         t->buffer_read = 0;
117                                                   117 
118       count++;                                    118       count++;
119                                                   119 
120       if (t->param & SOS_IOCTLPARAM_TTY_ECHO)     120       if (t->param & SOS_IOCTLPARAM_TTY_ECHO)
121         t->write (c);                             121         t->write (c);
122                                                   122 
123       sos_ksema_up (& t->sem);                    123       sos_ksema_up (& t->sem);
124                                                   124 
125       /* Did we read enough bytes ? */            125       /* Did we read enough bytes ? */
126       if (count == *len                           126       if (count == *len
127           || (c == '\n' && t->param & SOS_IOCT    127           || (c == '\n' && t->param & SOS_IOCTLPARAM_TTY_CANON))
128         break;                                    128         break;
129     }                                             129     }
130                                                   130 
131   *len = count;                                   131   *len = count;
132   return SOS_OK;                                  132   return SOS_OK;
133 }                                                 133 }
134                                                   134 
135                                                   135 
136 static sos_ret_t tty_write(struct sos_fs_opene    136 static sos_ret_t tty_write(struct sos_fs_opened_file *this,
137                            sos_uaddr_t src_buf    137                            sos_uaddr_t src_buf, sos_size_t *len)
138 {                                                 138 {
139   struct tty_device *t;                           139   struct tty_device *t;
140   char c;                                         140   char c;
141   int i;                                       !! 141   unsigned int i;
142   sos_ret_t ret;                                  142   sos_ret_t ret;
143                                                   143 
144   t = (struct tty_device *) this->custom_data;    144   t = (struct tty_device *) this->custom_data;
145                                                   145 
146   for (i = 0; i < *len; i++)                      146   for (i = 0; i < *len; i++)
147     {                                             147     {
148       ret = sos_memcpy_from_user ((sos_vaddr_t    148       ret = sos_memcpy_from_user ((sos_vaddr_t) & c, src_buf, sizeof(char));
149       if (sizeof(char) != ret)                    149       if (sizeof(char) != ret)
150         {                                         150         {
151           *len = i;                               151           *len = i;
152           return ret;                             152           return ret;
153         }                                         153         }
154                                                   154 
155       sos_ksema_down (& t->sem, NULL);            155       sos_ksema_down (& t->sem, NULL);
156       t->write (c);                               156       t->write (c);
157       sos_ksema_up (& t->sem);                    157       sos_ksema_up (& t->sem);
158                                                   158 
159       src_buf++;                                  159       src_buf++;
160     }                                             160     }
161                                                   161 
162   return SOS_OK;                                  162   return SOS_OK;
163 }                                                 163 }
164                                                   164 
165                                                   165 
166 static sos_ret_t tty_ioctl(struct sos_fs_opene    166 static sos_ret_t tty_ioctl(struct sos_fs_opened_file *this, int req_id,
167                            sos_ui32_t req_arg)    167                            sos_ui32_t req_arg)
168 {                                                 168 {
169   struct tty_device *t;                           169   struct tty_device *t;
170                                                   170 
171   if (req_arg != SOS_IOCTLPARAM_TTY_ECHO          171   if (req_arg != SOS_IOCTLPARAM_TTY_ECHO
172       && req_arg != SOS_IOCTLPARAM_TTY_CANON)     172       && req_arg != SOS_IOCTLPARAM_TTY_CANON)
173     return -SOS_EINVAL;                           173     return -SOS_EINVAL;
174                                                   174 
175   t = (struct tty_device *) this->custom_data;    175   t = (struct tty_device *) this->custom_data;
176                                                   176 
177   sos_ksema_down (& t->sem, NULL);                177   sos_ksema_down (& t->sem, NULL);
178                                                   178 
179   switch (req_id)                                 179   switch (req_id)
180     {                                             180     {
181     case SOS_IOCTL_TTY_SETPARAM:                  181     case SOS_IOCTL_TTY_SETPARAM:
182       t->param |= req_arg;                        182       t->param |= req_arg;
183       break;                                      183       break;
184                                                   184 
185     case SOS_IOCTL_TTY_RESETPARAM:                185     case SOS_IOCTL_TTY_RESETPARAM:
186       t->param &= ~req_arg;                       186       t->param &= ~req_arg;
187       break;                                      187       break;
188                                                   188 
189     default:                                      189     default:
190       sos_ksema_up (& t->sem);                    190       sos_ksema_up (& t->sem);
191       return -SOS_EINVAL;                         191       return -SOS_EINVAL;
192     }                                             192     }
193                                                   193 
194   sos_ksema_up (& t->sem);                        194   sos_ksema_up (& t->sem);
195                                                   195 
196   return SOS_OK;                                  196   return SOS_OK;
197 }                                                 197 }
198                                                   198 
199 static sos_ret_t tty_open(struct sos_fs_node      199 static sos_ret_t tty_open(struct sos_fs_node        * fsnode,
200                           struct sos_fs_opened    200                           struct sos_fs_opened_file * of,
201                           void * chardev_class    201                           void * chardev_class_custom_data)
202 {                                                 202 {
203   struct tty_device *t;                           203   struct tty_device *t;
204                                                   204 
205   t = tty_device_find (fsnode->dev_id.device_i    205   t = tty_device_find (fsnode->dev_id.device_instance);
206   if (t == NULL)                                  206   if (t == NULL)
207     return -SOS_ENOENT;                           207     return -SOS_ENOENT;
208                                                   208 
209   sos_ksema_down (& t->sem, NULL);                209   sos_ksema_down (& t->sem, NULL);
210   of->custom_data = t;                            210   of->custom_data = t;
211   t->open_count ++;                               211   t->open_count ++;
212   sos_ksema_up (& t->sem);                        212   sos_ksema_up (& t->sem);
213                                                   213 
214   return SOS_OK;                                  214   return SOS_OK;
215 }                                                 215 }
216                                                   216 
217                                                   217 
218 static sos_ret_t tty_close(struct sos_fs_opene    218 static sos_ret_t tty_close(struct sos_fs_opened_file *of,
219                            void *custom_data)     219                            void *custom_data)
220 {                                                 220 {
221   struct tty_device *t;                           221   struct tty_device *t;
222                                                   222 
223   t = (struct tty_device *) of->custom_data;      223   t = (struct tty_device *) of->custom_data;
224                                                   224 
225   sos_ksema_down (& t->sem, NULL);                225   sos_ksema_down (& t->sem, NULL);
226   t->open_count --;                               226   t->open_count --;
227   sos_ksema_up (& t->sem);                        227   sos_ksema_up (& t->sem);
228                                                   228 
229   return SOS_OK;                                  229   return SOS_OK;
230 }                                                 230 }
231                                                   231 
232 void tty_add_chars (struct tty_device *t, cons    232 void tty_add_chars (struct tty_device *t, const char *s)
233 {                                                 233 {
234   sos_ksema_down (& t->sem, NULL);                234   sos_ksema_down (& t->sem, NULL);
235   while (*s)                                      235   while (*s)
236     {                                             236     {
237       /* Add all characters to the ring buffer    237       /* Add all characters to the ring buffer */
238       t->buffer[t->buffer_write] = *s;            238       t->buffer[t->buffer_write] = *s;
239       t->buffer_write++;                          239       t->buffer_write++;
240       if (t->buffer_write == TTY_BUFFER_LEN)      240       if (t->buffer_write == TTY_BUFFER_LEN)
241         t->buffer_write = 0;                      241         t->buffer_write = 0;
242       s++;                                        242       s++;
243     }                                             243     }
244   sos_ksema_up (& t->sem);                        244   sos_ksema_up (& t->sem);
245                                                   245 
246   /* Wake up a possibly waiting thread */         246   /* Wake up a possibly waiting thread */
247   sos_kwaitq_wakeup (& t->wq, SOS_KWQ_WAKEUP_A    247   sos_kwaitq_wakeup (& t->wq, SOS_KWQ_WAKEUP_ALL, SOS_OK);
248 }                                                 248 }
249                                                   249 
250 struct sos_chardev_ops tty_ops = {                250 struct sos_chardev_ops tty_ops = {
251   .read    = tty_read,                            251   .read    = tty_read,
252   .write   = tty_write,                           252   .write   = tty_write,
253   .open    = tty_open,                            253   .open    = tty_open,
254   .close   = tty_close,                           254   .close   = tty_close,
255   .ioctl   = tty_ioctl                            255   .ioctl   = tty_ioctl
256 };                                                256 };
257                                                   257 
258 sos_ret_t tty_create (sos_ui32_t device_instan    258 sos_ret_t tty_create (sos_ui32_t device_instance,
259                       sos_ret_t (*write_func)     259                       sos_ret_t (*write_func) (char c),
260                       struct tty_device **tty_    260                       struct tty_device **tty_out)
261 {                                                 261 {
262   struct tty_device *tty;                         262   struct tty_device *tty;
263                                                   263 
264   if (tty_device_find (device_instance) != NUL    264   if (tty_device_find (device_instance) != NULL)
265     return -SOS_EBUSY;                            265     return -SOS_EBUSY;
266                                                   266 
267   tty = (struct tty_device *) sos_kmalloc (siz    267   tty = (struct tty_device *) sos_kmalloc (sizeof(struct tty_device), 0);
268   if (tty == NULL)                                268   if (tty == NULL)
269     return -SOS_ENOMEM;                           269     return -SOS_ENOMEM;
270                                                   270 
271   memset (tty->buffer, 0, sizeof(tty->buffer))    271   memset (tty->buffer, 0, sizeof(tty->buffer));
272   tty->open_count   = 0;                          272   tty->open_count   = 0;
273   tty->instance     = device_instance;            273   tty->instance     = device_instance;
274   tty->write        = write_func;                 274   tty->write        = write_func;
275   tty->buffer_read  = 0;                          275   tty->buffer_read  = 0;
276   tty->buffer_write = 0;                          276   tty->buffer_write = 0;
277   tty->param        = SOS_IOCTLPARAM_TTY_CANON    277   tty->param        = SOS_IOCTLPARAM_TTY_CANON;
278   sos_kwaitq_init(& tty->wq, "tty", SOS_KWQ_OR    278   sos_kwaitq_init(& tty->wq, "tty", SOS_KWQ_ORDER_FIFO);
279   sos_ksema_init(& tty->sem, "tty", 1, SOS_KWQ    279   sos_ksema_init(& tty->sem, "tty", 1, SOS_KWQ_ORDER_FIFO);
280                                                   280 
281   list_add_tail (tty_device_list, tty);           281   list_add_tail (tty_device_list, tty);
282                                                   282 
283   *tty_out = tty;                                 283   *tty_out = tty;
284                                                   284 
285   return SOS_OK;                                  285   return SOS_OK;
286 }                                                 286 }
287                                                   287 
288 sos_ret_t tty_remove (struct tty_device *tty)     288 sos_ret_t tty_remove (struct tty_device *tty)
289 {                                                 289 {
290   if (tty == NULL)                                290   if (tty == NULL)
291     return -SOS_EINVAL;                           291     return -SOS_EINVAL;
292                                                   292 
293   if (SOS_OK != sos_ksema_trydown (& tty->sem)    293   if (SOS_OK != sos_ksema_trydown (& tty->sem))
294     return -SOS_EBUSY;                            294     return -SOS_EBUSY;
295                                                   295 
296   if (tty->open_count != 0)                       296   if (tty->open_count != 0)
297     return -SOS_EBUSY;                            297     return -SOS_EBUSY;
298                                                   298 
299   sos_kwaitq_dispose (& tty->wq);                 299   sos_kwaitq_dispose (& tty->wq);
300   list_delete (tty_device_list, tty);             300   list_delete (tty_device_list, tty);
301                                                   301 
302   sos_kfree ((sos_vaddr_t) tty);                  302   sos_kfree ((sos_vaddr_t) tty);
303                                                   303 
304   return SOS_OK;                                  304   return SOS_OK;
305 }                                                 305 }
306                                                   306 
307 sos_ret_t tty_subsystem_setup (void)              307 sos_ret_t tty_subsystem_setup (void)
308 {                                                 308 {
309   list_init (tty_device_list);                    309   list_init (tty_device_list);
310   return sos_chardev_register_class (SOS_CHARD    310   return sos_chardev_register_class (SOS_CHARDEV_TTY_MAJOR,
311                                      & tty_ops    311                                      & tty_ops, NULL);
312 }                                                 312 }
313                                                   313 
314 sos_ret_t tty_subsystem_cleanup (void)            314 sos_ret_t tty_subsystem_cleanup (void)
315 {                                                 315 {
316   return sos_chardev_unregister_class (SOS_CHA    316   return sos_chardev_unregister_class (SOS_CHARDEV_TTY_MAJOR);
317 }                                                 317 }
318                                                   318 
                                                      

source navigation ] diff markup ] identifier search ] general search ]